Skip to content

Commit 09f5f68

Browse files
amboarcminyard
authored andcommitted
ipmi: kcs: aspeed: Implement v2 bindings
The v2 bindings allow us to extract the resources from the devicetree. The table in the driver is retained to derive the channel index, which removes the need for kcs_chan property from the v1 bindings. The v2 bindings allow us to reduce the number of warnings generated by the existing devicetree nodes. Signed-off-by: Andrew Jeffery <[email protected]> Reviewed-by: Joel Stanley <[email protected]> Reviewed-by: Haiyue Wang <[email protected]> Message-Id: <01ef3787e9ddaa9d87cfd55a2ac793053b5a69de.1576462051.git-series.andrew@aj.id.au> Signed-off-by: Corey Minyard <[email protected]>
1 parent af6432c commit 09f5f68

File tree

1 file changed

+121
-23
lines changed

1 file changed

+121
-23
lines changed

drivers/char/ipmi/kcs_bmc_aspeed.c

Lines changed: 121 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/mfd/syscon.h>
1313
#include <linux/module.h>
1414
#include <linux/of.h>
15+
#include <linux/of_address.h>
1516
#include <linux/platform_device.h>
1617
#include <linux/poll.h>
1718
#include <linux/regmap.h>
@@ -233,38 +234,133 @@ static const struct kcs_ioreg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = {
233234
{ .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 },
234235
};
235236

236-
static int aspeed_kcs_probe(struct platform_device *pdev)
237+
static struct kcs_bmc *aspeed_kcs_probe_of_v1(struct platform_device *pdev)
237238
{
238-
struct device *dev = &pdev->dev;
239239
struct aspeed_kcs_bmc *priv;
240-
struct kcs_bmc *kcs_bmc;
241-
u32 chan, addr;
240+
struct device_node *np;
241+
struct kcs_bmc *kcs;
242+
u32 channel;
243+
u32 slave;
242244
int rc;
243245

244-
rc = of_property_read_u32(dev->of_node, "kcs_chan", &chan);
245-
if ((rc != 0) || (chan == 0 || chan > KCS_CHANNEL_MAX)) {
246-
dev_err(dev, "no valid 'kcs_chan' configured\n");
247-
return -ENODEV;
246+
np = pdev->dev.of_node;
247+
248+
rc = of_property_read_u32(np, "kcs_chan", &channel);
249+
if ((rc != 0) || (channel == 0 || channel > KCS_CHANNEL_MAX)) {
250+
dev_err(&pdev->dev, "no valid 'kcs_chan' configured\n");
251+
return ERR_PTR(-EINVAL);
248252
}
249253

250-
rc = of_property_read_u32(dev->of_node, "kcs_addr", &addr);
254+
kcs = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel);
255+
if (!kcs)
256+
return ERR_PTR(-ENOMEM);
257+
258+
priv = kcs_bmc_priv(kcs);
259+
priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node);
260+
if (IS_ERR(priv->map)) {
261+
dev_err(&pdev->dev, "Couldn't get regmap\n");
262+
return ERR_PTR(-ENODEV);
263+
}
264+
265+
rc = of_property_read_u32(np, "kcs_addr", &slave);
251266
if (rc) {
252-
dev_err(dev, "no valid 'kcs_addr' configured\n");
253-
return -ENODEV;
267+
dev_err(&pdev->dev, "no valid 'kcs_addr' configured\n");
268+
return ERR_PTR(-EINVAL);
254269
}
255270

256-
kcs_bmc = kcs_bmc_alloc(dev, sizeof(*priv), chan);
257-
if (!kcs_bmc)
258-
return -ENOMEM;
271+
kcs->ioreg = ast_kcs_bmc_ioregs[channel - 1];
272+
aspeed_kcs_set_address(kcs, slave);
273+
274+
return 0;
275+
}
276+
277+
static int aspeed_kcs_calculate_channel(const struct kcs_ioreg *regs)
278+
{
279+
int i;
280+
281+
for (i = 0; i < ARRAY_SIZE(ast_kcs_bmc_ioregs); i++) {
282+
if (!memcmp(&ast_kcs_bmc_ioregs[i], regs, sizeof(*regs)))
283+
return i + 1;
284+
}
285+
286+
return -EINVAL;
287+
}
288+
289+
static struct kcs_bmc *aspeed_kcs_probe_of_v2(struct platform_device *pdev)
290+
{
291+
struct aspeed_kcs_bmc *priv;
292+
struct device_node *np;
293+
struct kcs_ioreg ioreg;
294+
struct kcs_bmc *kcs;
295+
const __be32 *reg;
296+
int channel;
297+
u32 slave;
298+
int rc;
259299

260-
priv = kcs_bmc_priv(kcs_bmc);
261-
priv->map = syscon_node_to_regmap(dev->parent->of_node);
300+
np = pdev->dev.of_node;
301+
302+
/* Don't translate addresses, we want offsets for the regmaps */
303+
reg = of_get_address(np, 0, NULL, NULL);
304+
if (!reg)
305+
return ERR_PTR(-EINVAL);
306+
ioreg.idr = be32_to_cpup(reg);
307+
308+
reg = of_get_address(np, 1, NULL, NULL);
309+
if (!reg)
310+
return ERR_PTR(-EINVAL);
311+
ioreg.odr = be32_to_cpup(reg);
312+
313+
reg = of_get_address(np, 2, NULL, NULL);
314+
if (!reg)
315+
return ERR_PTR(-EINVAL);
316+
ioreg.str = be32_to_cpup(reg);
317+
318+
channel = aspeed_kcs_calculate_channel(&ioreg);
319+
if (channel < 0)
320+
return ERR_PTR(channel);
321+
322+
kcs = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel);
323+
if (!kcs)
324+
return ERR_PTR(-ENOMEM);
325+
326+
kcs->ioreg = ioreg;
327+
328+
priv = kcs_bmc_priv(kcs);
329+
priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node);
262330
if (IS_ERR(priv->map)) {
263-
dev_err(dev, "Couldn't get regmap\n");
264-
return -ENODEV;
331+
dev_err(&pdev->dev, "Couldn't get regmap\n");
332+
return ERR_PTR(-ENODEV);
265333
}
266334

267-
kcs_bmc->ioreg = ast_kcs_bmc_ioregs[chan - 1];
335+
rc = of_property_read_u32(np, "aspeed,lpc-io-reg", &slave);
336+
if (rc)
337+
return ERR_PTR(rc);
338+
339+
aspeed_kcs_set_address(kcs, slave);
340+
341+
return kcs;
342+
}
343+
344+
static int aspeed_kcs_probe(struct platform_device *pdev)
345+
{
346+
struct device *dev = &pdev->dev;
347+
struct kcs_bmc *kcs_bmc;
348+
struct device_node *np;
349+
int rc;
350+
351+
np = pdev->dev.of_node;
352+
if (of_device_is_compatible(np, "aspeed,ast2400-kcs-bmc") ||
353+
of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc"))
354+
kcs_bmc = aspeed_kcs_probe_of_v1(pdev);
355+
else if (of_device_is_compatible(np, "aspeed,ast2400-kcs-bmc-v2") ||
356+
of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc-v2"))
357+
kcs_bmc = aspeed_kcs_probe_of_v2(pdev);
358+
else
359+
return -EINVAL;
360+
361+
if (IS_ERR(kcs_bmc))
362+
return PTR_ERR(kcs_bmc);
363+
268364
kcs_bmc->io_inputb = aspeed_kcs_inb;
269365
kcs_bmc->io_outputb = aspeed_kcs_outb;
270366

@@ -274,7 +370,6 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
274370

275371
dev_set_drvdata(dev, kcs_bmc);
276372

277-
aspeed_kcs_set_address(kcs_bmc, addr);
278373
aspeed_kcs_enable_channel(kcs_bmc, true);
279374

280375
rc = misc_register(&kcs_bmc->miscdev);
@@ -283,9 +378,10 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
283378
return rc;
284379
}
285380

286-
pr_info("channel=%u addr=0x%x idr=0x%x odr=0x%x str=0x%x\n",
287-
chan, addr,
288-
kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str);
381+
dev_dbg(&pdev->dev,
382+
"Probed KCS device %d (IDR=0x%x, ODR=0x%x, STR=0x%x)\n",
383+
kcs_bmc->channel, kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr,
384+
kcs_bmc->ioreg.str);
289385

290386
return 0;
291387
}
@@ -302,6 +398,8 @@ static int aspeed_kcs_remove(struct platform_device *pdev)
302398
static const struct of_device_id ast_kcs_bmc_match[] = {
303399
{ .compatible = "aspeed,ast2400-kcs-bmc" },
304400
{ .compatible = "aspeed,ast2500-kcs-bmc" },
401+
{ .compatible = "aspeed,ast2400-kcs-bmc-v2" },
402+
{ .compatible = "aspeed,ast2500-kcs-bmc-v2" },
305403
{ }
306404
};
307405
MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match);

0 commit comments

Comments
 (0)