Skip to content

Commit d0ec795

Browse files
amboarcminyard
authored andcommitted
ipmi: kcs_bmc_aspeed: Optionally apply status address
Some Aspeed KCS devices can derive the status register address from the address of the data register. As such, the address of the status register can be implicit in the configuration if desired. On the other hand, sometimes address schemes might be requested that are incompatible with the default addressing scheme. Allow these requests where possible if the devicetree specifies the status register address. Signed-off-by: Andrew Jeffery <[email protected]> Reviewed-by: Chia-Wei Wang <[email protected]> Message-Id: <[email protected]> Signed-off-by: Corey Minyard <[email protected]>
1 parent 78ff5a1 commit d0ec795

File tree

1 file changed

+83
-33
lines changed

1 file changed

+83
-33
lines changed

drivers/char/ipmi/kcs_bmc_aspeed.c

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@
8383
#define LPC_STR2 0x040
8484
#define LPC_STR3 0x044
8585
#define LPC_HICRB 0x100
86+
#define LPC_HICRB_EN16LADR2 BIT(5)
87+
#define LPC_HICRB_EN16LADR1 BIT(4)
8688
#define LPC_HICRB_IBFIE4 BIT(1)
8789
#define LPC_HICRB_LPC4E BIT(0)
8890
#define LPC_HICRC 0x104
@@ -96,6 +98,11 @@
9698
#define LPC_IDR4 0x114
9799
#define LPC_ODR4 0x118
98100
#define LPC_STR4 0x11C
101+
#define LPC_LSADR12 0x120
102+
#define LPC_LSADR12_LSADR2_MASK GENMASK(31, 16)
103+
#define LPC_LSADR12_LSADR2_SHIFT 16
104+
#define LPC_LSADR12_LSADR1_MASK GENMASK(15, 0)
105+
#define LPC_LSADR12_LSADR1_SHIFT 0
99106

100107
#define OBE_POLL_PERIOD (HZ / 2)
101108

@@ -123,7 +130,7 @@ struct aspeed_kcs_bmc {
123130

124131
struct aspeed_kcs_of_ops {
125132
int (*get_channel)(struct platform_device *pdev);
126-
int (*get_io_address)(struct platform_device *pdev);
133+
int (*get_io_address)(struct platform_device *pdev, u32 addrs[2]);
127134
};
128135

129136
static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc_device *kcs_bmc)
@@ -217,38 +224,64 @@ static void aspeed_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask,
217224
* C. KCS4
218225
* D / C : CA4h / CA5h
219226
*/
220-
static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr)
227+
static int aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u32 addrs[2], int nr_addrs)
221228
{
222229
struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc);
223230

224-
switch (kcs_bmc->channel) {
231+
if (WARN_ON(nr_addrs < 1 || nr_addrs > 2))
232+
return -EINVAL;
233+
234+
switch (priv->kcs_bmc.channel) {
225235
case 1:
226-
regmap_update_bits(priv->map, LPC_HICR4,
227-
LPC_HICR4_LADR12AS, 0);
228-
regmap_write(priv->map, LPC_LADR12H, addr >> 8);
229-
regmap_write(priv->map, LPC_LADR12L, addr & 0xFF);
236+
regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_LADR12AS, 0);
237+
regmap_write(priv->map, LPC_LADR12H, addrs[0] >> 8);
238+
regmap_write(priv->map, LPC_LADR12L, addrs[0] & 0xFF);
239+
if (nr_addrs == 2) {
240+
regmap_update_bits(priv->map, LPC_LSADR12, LPC_LSADR12_LSADR1_MASK,
241+
addrs[1] << LPC_LSADR12_LSADR1_SHIFT);
242+
243+
regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_EN16LADR1,
244+
LPC_HICRB_EN16LADR1);
245+
}
230246
break;
231247

232248
case 2:
233-
regmap_update_bits(priv->map, LPC_HICR4,
234-
LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS);
235-
regmap_write(priv->map, LPC_LADR12H, addr >> 8);
236-
regmap_write(priv->map, LPC_LADR12L, addr & 0xFF);
249+
regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS);
250+
regmap_write(priv->map, LPC_LADR12H, addrs[0] >> 8);
251+
regmap_write(priv->map, LPC_LADR12L, addrs[0] & 0xFF);
252+
if (nr_addrs == 2) {
253+
regmap_update_bits(priv->map, LPC_LSADR12, LPC_LSADR12_LSADR2_MASK,
254+
addrs[1] << LPC_LSADR12_LSADR2_SHIFT);
255+
256+
regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_EN16LADR2,
257+
LPC_HICRB_EN16LADR2);
258+
}
237259
break;
238260

239261
case 3:
240-
regmap_write(priv->map, LPC_LADR3H, addr >> 8);
241-
regmap_write(priv->map, LPC_LADR3L, addr & 0xFF);
262+
if (nr_addrs == 2) {
263+
dev_err(priv->kcs_bmc.dev,
264+
"Channel 3 only supports inferred status IO address\n");
265+
return -EINVAL;
266+
}
267+
268+
regmap_write(priv->map, LPC_LADR3H, addrs[0] >> 8);
269+
regmap_write(priv->map, LPC_LADR3L, addrs[0] & 0xFF);
242270
break;
243271

244272
case 4:
245-
regmap_write(priv->map, LPC_LADR4, ((addr + 1) << 16) |
246-
addr);
273+
if (nr_addrs == 1)
274+
regmap_write(priv->map, LPC_LADR4, ((addrs[0] + 1) << 16) | addrs[0]);
275+
else
276+
regmap_write(priv->map, LPC_LADR4, (addrs[1] << 16) | addrs[0]);
277+
247278
break;
248279

249280
default:
250-
break;
281+
return -EINVAL;
251282
}
283+
284+
return 0;
252285
}
253286

254287
static inline int aspeed_kcs_map_serirq_type(u32 dt_type)
@@ -457,18 +490,18 @@ static int aspeed_kcs_of_v1_get_channel(struct platform_device *pdev)
457490
return channel;
458491
}
459492

460-
static int aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev)
493+
static int
494+
aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev, u32 addrs[2])
461495
{
462-
u32 slave;
463496
int rc;
464497

465-
rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", &slave);
466-
if (rc || slave > 0xffff) {
498+
rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", addrs);
499+
if (rc || addrs[0] > 0xffff) {
467500
dev_err(&pdev->dev, "no valid 'kcs_addr' configured\n");
468501
return -EINVAL;
469502
}
470503

471-
return slave;
504+
return 1;
472505
}
473506

474507
static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev)
@@ -504,18 +537,30 @@ static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev)
504537
return -EINVAL;
505538
}
506539

507-
static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev)
540+
static int
541+
aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev, u32 addrs[2])
508542
{
509-
uint32_t slave;
510543
int rc;
511544

512-
rc = of_property_read_u32(pdev->dev.of_node, "aspeed,lpc-io-reg", &slave);
513-
if (rc || slave > 0xffff) {
514-
dev_err(&pdev->dev, "no valid 'aspeed,lpc-io-reg' configured\n");
545+
rc = of_property_read_variable_u32_array(pdev->dev.of_node,
546+
"aspeed,lpc-io-reg",
547+
addrs, 1, 2);
548+
if (rc < 0) {
549+
dev_err(&pdev->dev, "No valid 'aspeed,lpc-io-reg' configured\n");
550+
return rc;
551+
}
552+
553+
if (addrs[0] > 0xffff) {
554+
dev_err(&pdev->dev, "Invalid data address in 'aspeed,lpc-io-reg'\n");
555+
return -EINVAL;
556+
}
557+
558+
if (rc == 2 && addrs[1] > 0xffff) {
559+
dev_err(&pdev->dev, "Invalid status address in 'aspeed,lpc-io-reg'\n");
515560
return -EINVAL;
516561
}
517562

518-
return slave;
563+
return rc;
519564
}
520565

521566
static int aspeed_kcs_probe(struct platform_device *pdev)
@@ -524,9 +569,11 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
524569
struct kcs_bmc_device *kcs_bmc;
525570
struct aspeed_kcs_bmc *priv;
526571
struct device_node *np;
527-
int rc, channel, addr;
528572
bool have_upstream_irq;
529573
u32 upstream_irq[2];
574+
int rc, channel;
575+
int nr_addrs;
576+
u32 addrs[2];
530577

531578
np = pdev->dev.of_node->parent;
532579
if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") &&
@@ -544,9 +591,9 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
544591
if (channel < 0)
545592
return channel;
546593

547-
addr = ops->get_io_address(pdev);
548-
if (addr < 0)
549-
return addr;
594+
nr_addrs = ops->get_io_address(pdev, addrs);
595+
if (nr_addrs < 0)
596+
return nr_addrs;
550597

551598
np = pdev->dev.of_node;
552599
rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", upstream_irq, 2);
@@ -575,7 +622,9 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
575622
priv->obe.remove = false;
576623
timer_setup(&priv->obe.timer, aspeed_kcs_check_obe, 0);
577624

578-
aspeed_kcs_set_address(kcs_bmc, addr);
625+
rc = aspeed_kcs_set_address(kcs_bmc, addrs, nr_addrs);
626+
if (rc)
627+
return rc;
579628

580629
/* Host to BMC IRQ */
581630
rc = aspeed_kcs_config_downstream_irq(kcs_bmc, pdev);
@@ -602,7 +651,8 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
602651
return rc;
603652
}
604653

605-
dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n", kcs_bmc->channel, addr);
654+
dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n",
655+
kcs_bmc->channel, addrs[0]);
606656

607657
return 0;
608658
}

0 commit comments

Comments
 (0)