diff options
-rw-r--r-- | Documentation/IPMI.txt | 2 | ||||
-rw-r--r-- | drivers/acpi/acpi_ipmi.c | 2 | ||||
-rw-r--r-- | drivers/char/ipmi/Kconfig | 3 | ||||
-rw-r--r-- | drivers/char/ipmi/bt-bmc.c | 80 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_devintf.c | 2 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 4 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_powernv.c | 2 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_watchdog.c | 2 | ||||
-rw-r--r-- | include/linux/ipmi.h | 2 |
9 files changed, 69 insertions, 30 deletions
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt index 72292308d0f5..6962cab997ef 100644 --- a/Documentation/IPMI.txt +++ b/Documentation/IPMI.txt | |||
@@ -257,7 +257,7 @@ and tell you when they come and go. | |||
257 | 257 | ||
258 | Creating the User | 258 | Creating the User |
259 | 259 | ||
260 | To user the message handler, you must first create a user using | 260 | To use the message handler, you must first create a user using |
261 | ipmi_create_user. The interface number specifies which SMI you want | 261 | ipmi_create_user. The interface number specifies which SMI you want |
262 | to connect to, and you must supply callback functions to be called | 262 | to connect to, and you must supply callback functions to be called |
263 | when data comes in. The callback function can run at interrupt level, | 263 | when data comes in. The callback function can run at interrupt level, |
diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index f77956c3fd45..747c2ba98534 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c | |||
@@ -56,7 +56,7 @@ struct acpi_ipmi_device { | |||
56 | struct ipmi_driver_data { | 56 | struct ipmi_driver_data { |
57 | struct list_head ipmi_devices; | 57 | struct list_head ipmi_devices; |
58 | struct ipmi_smi_watcher bmc_events; | 58 | struct ipmi_smi_watcher bmc_events; |
59 | struct ipmi_user_hndl ipmi_hndlrs; | 59 | const struct ipmi_user_hndl ipmi_hndlrs; |
60 | struct mutex ipmi_lock; | 60 | struct mutex ipmi_lock; |
61 | 61 | ||
62 | /* | 62 | /* |
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index 7f816655cbbf..90f3edffb067 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig | |||
@@ -78,7 +78,8 @@ config IPMI_POWEROFF | |||
78 | endif # IPMI_HANDLER | 78 | endif # IPMI_HANDLER |
79 | 79 | ||
80 | config ASPEED_BT_IPMI_BMC | 80 | config ASPEED_BT_IPMI_BMC |
81 | depends on ARCH_ASPEED | 81 | depends on ARCH_ASPEED || COMPILE_TEST |
82 | depends on REGMAP && REGMAP_MMIO && MFD_SYSCON | ||
82 | tristate "BT IPMI bmc driver" | 83 | tristate "BT IPMI bmc driver" |
83 | help | 84 | help |
84 | Provides a driver for the BT (Block Transfer) IPMI interface | 85 | Provides a driver for the BT (Block Transfer) IPMI interface |
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c index fc9e8891eae3..d6f5d9eb102d 100644 --- a/drivers/char/ipmi/bt-bmc.c +++ b/drivers/char/ipmi/bt-bmc.c | |||
@@ -12,10 +12,13 @@ | |||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/mfd/syscon.h> | ||
15 | #include <linux/miscdevice.h> | 16 | #include <linux/miscdevice.h> |
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/of.h> | ||
17 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
18 | #include <linux/poll.h> | 20 | #include <linux/poll.h> |
21 | #include <linux/regmap.h> | ||
19 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
20 | #include <linux/timer.h> | 23 | #include <linux/timer.h> |
21 | 24 | ||
@@ -60,7 +63,8 @@ | |||
60 | struct bt_bmc { | 63 | struct bt_bmc { |
61 | struct device dev; | 64 | struct device dev; |
62 | struct miscdevice miscdev; | 65 | struct miscdevice miscdev; |
63 | void __iomem *base; | 66 | struct regmap *map; |
67 | int offset; | ||
64 | int irq; | 68 | int irq; |
65 | wait_queue_head_t queue; | 69 | wait_queue_head_t queue; |
66 | struct timer_list poll_timer; | 70 | struct timer_list poll_timer; |
@@ -69,14 +73,29 @@ struct bt_bmc { | |||
69 | 73 | ||
70 | static atomic_t open_count = ATOMIC_INIT(0); | 74 | static atomic_t open_count = ATOMIC_INIT(0); |
71 | 75 | ||
76 | static const struct regmap_config bt_regmap_cfg = { | ||
77 | .reg_bits = 32, | ||
78 | .val_bits = 32, | ||
79 | .reg_stride = 4, | ||
80 | }; | ||
81 | |||
72 | static u8 bt_inb(struct bt_bmc *bt_bmc, int reg) | 82 | static u8 bt_inb(struct bt_bmc *bt_bmc, int reg) |
73 | { | 83 | { |
74 | return ioread8(bt_bmc->base + reg); | 84 | uint32_t val = 0; |
85 | int rc; | ||
86 | |||
87 | rc = regmap_read(bt_bmc->map, bt_bmc->offset + reg, &val); | ||
88 | WARN(rc != 0, "regmap_read() failed: %d\n", rc); | ||
89 | |||
90 | return rc == 0 ? (u8) val : 0; | ||
75 | } | 91 | } |
76 | 92 | ||
77 | static void bt_outb(struct bt_bmc *bt_bmc, u8 data, int reg) | 93 | static void bt_outb(struct bt_bmc *bt_bmc, u8 data, int reg) |
78 | { | 94 | { |
79 | iowrite8(data, bt_bmc->base + reg); | 95 | int rc; |
96 | |||
97 | rc = regmap_write(bt_bmc->map, bt_bmc->offset + reg, data); | ||
98 | WARN(rc != 0, "regmap_write() failed: %d\n", rc); | ||
80 | } | 99 | } |
81 | 100 | ||
82 | static void clr_rd_ptr(struct bt_bmc *bt_bmc) | 101 | static void clr_rd_ptr(struct bt_bmc *bt_bmc) |
@@ -367,14 +386,18 @@ static irqreturn_t bt_bmc_irq(int irq, void *arg) | |||
367 | { | 386 | { |
368 | struct bt_bmc *bt_bmc = arg; | 387 | struct bt_bmc *bt_bmc = arg; |
369 | u32 reg; | 388 | u32 reg; |
389 | int rc; | ||
390 | |||
391 | rc = regmap_read(bt_bmc->map, bt_bmc->offset + BT_CR2, ®); | ||
392 | if (rc) | ||
393 | return IRQ_NONE; | ||
370 | 394 | ||
371 | reg = ioread32(bt_bmc->base + BT_CR2); | ||
372 | reg &= BT_CR2_IRQ_H2B | BT_CR2_IRQ_HBUSY; | 395 | reg &= BT_CR2_IRQ_H2B | BT_CR2_IRQ_HBUSY; |
373 | if (!reg) | 396 | if (!reg) |
374 | return IRQ_NONE; | 397 | return IRQ_NONE; |
375 | 398 | ||
376 | /* ack pending IRQs */ | 399 | /* ack pending IRQs */ |
377 | iowrite32(reg, bt_bmc->base + BT_CR2); | 400 | regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR2, reg); |
378 | 401 | ||
379 | wake_up(&bt_bmc->queue); | 402 | wake_up(&bt_bmc->queue); |
380 | return IRQ_HANDLED; | 403 | return IRQ_HANDLED; |
@@ -384,7 +407,6 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc, | |||
384 | struct platform_device *pdev) | 407 | struct platform_device *pdev) |
385 | { | 408 | { |
386 | struct device *dev = &pdev->dev; | 409 | struct device *dev = &pdev->dev; |
387 | u32 reg; | ||
388 | int rc; | 410 | int rc; |
389 | 411 | ||
390 | bt_bmc->irq = platform_get_irq(pdev, 0); | 412 | bt_bmc->irq = platform_get_irq(pdev, 0); |
@@ -405,18 +427,17 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc, | |||
405 | * will be cleared (along with B2H) when we can write the next | 427 | * will be cleared (along with B2H) when we can write the next |
406 | * message to the BT buffer | 428 | * message to the BT buffer |
407 | */ | 429 | */ |
408 | reg = ioread32(bt_bmc->base + BT_CR1); | 430 | rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + BT_CR1, |
409 | reg |= BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY; | 431 | (BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY), |
410 | iowrite32(reg, bt_bmc->base + BT_CR1); | 432 | (BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY)); |
411 | 433 | ||
412 | return 0; | 434 | return rc; |
413 | } | 435 | } |
414 | 436 | ||
415 | static int bt_bmc_probe(struct platform_device *pdev) | 437 | static int bt_bmc_probe(struct platform_device *pdev) |
416 | { | 438 | { |
417 | struct bt_bmc *bt_bmc; | 439 | struct bt_bmc *bt_bmc; |
418 | struct device *dev; | 440 | struct device *dev; |
419 | struct resource *res; | ||
420 | int rc; | 441 | int rc; |
421 | 442 | ||
422 | if (!pdev || !pdev->dev.of_node) | 443 | if (!pdev || !pdev->dev.of_node) |
@@ -431,10 +452,27 @@ static int bt_bmc_probe(struct platform_device *pdev) | |||
431 | 452 | ||
432 | dev_set_drvdata(&pdev->dev, bt_bmc); | 453 | dev_set_drvdata(&pdev->dev, bt_bmc); |
433 | 454 | ||
434 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 455 | bt_bmc->map = syscon_node_to_regmap(pdev->dev.parent->of_node); |
435 | bt_bmc->base = devm_ioremap_resource(&pdev->dev, res); | 456 | if (IS_ERR(bt_bmc->map)) { |
436 | if (IS_ERR(bt_bmc->base)) | 457 | struct resource *res; |
437 | return PTR_ERR(bt_bmc->base); | 458 | void __iomem *base; |
459 | |||
460 | /* | ||
461 | * Assume it's not the MFD-based devicetree description, in | ||
462 | * which case generate a regmap ourselves | ||
463 | */ | ||
464 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
465 | base = devm_ioremap_resource(&pdev->dev, res); | ||
466 | if (IS_ERR(base)) | ||
467 | return PTR_ERR(base); | ||
468 | |||
469 | bt_bmc->map = devm_regmap_init_mmio(dev, base, &bt_regmap_cfg); | ||
470 | bt_bmc->offset = 0; | ||
471 | } else { | ||
472 | rc = of_property_read_u32(dev->of_node, "reg", &bt_bmc->offset); | ||
473 | if (rc) | ||
474 | return rc; | ||
475 | } | ||
438 | 476 | ||
439 | mutex_init(&bt_bmc->mutex); | 477 | mutex_init(&bt_bmc->mutex); |
440 | init_waitqueue_head(&bt_bmc->queue); | 478 | init_waitqueue_head(&bt_bmc->queue); |
@@ -461,12 +499,12 @@ static int bt_bmc_probe(struct platform_device *pdev) | |||
461 | add_timer(&bt_bmc->poll_timer); | 499 | add_timer(&bt_bmc->poll_timer); |
462 | } | 500 | } |
463 | 501 | ||
464 | iowrite32((BT_IO_BASE << BT_CR0_IO_BASE) | | 502 | regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0, |
465 | (BT_IRQ << BT_CR0_IRQ) | | 503 | (BT_IO_BASE << BT_CR0_IO_BASE) | |
466 | BT_CR0_EN_CLR_SLV_RDP | | 504 | (BT_IRQ << BT_CR0_IRQ) | |
467 | BT_CR0_EN_CLR_SLV_WRP | | 505 | BT_CR0_EN_CLR_SLV_RDP | |
468 | BT_CR0_ENABLE_IBT, | 506 | BT_CR0_EN_CLR_SLV_WRP | |
469 | bt_bmc->base + BT_CR0); | 507 | BT_CR0_ENABLE_IBT); |
470 | 508 | ||
471 | clr_b_busy(bt_bmc); | 509 | clr_b_busy(bt_bmc); |
472 | 510 | ||
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index a21407de46ae..f45119c5337d 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -108,7 +108,7 @@ static int ipmi_fasync(int fd, struct file *file, int on) | |||
108 | return (result); | 108 | return (result); |
109 | } | 109 | } |
110 | 110 | ||
111 | static struct ipmi_user_hndl ipmi_hndlrs = | 111 | static const struct ipmi_user_hndl ipmi_hndlrs = |
112 | { | 112 | { |
113 | .ipmi_recv_hndl = file_receive_handler, | 113 | .ipmi_recv_hndl = file_receive_handler, |
114 | }; | 114 | }; |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 92e53acf2cd2..9f699951b75a 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -102,7 +102,7 @@ struct ipmi_user { | |||
102 | struct kref refcount; | 102 | struct kref refcount; |
103 | 103 | ||
104 | /* The upper layer that handles receive messages. */ | 104 | /* The upper layer that handles receive messages. */ |
105 | struct ipmi_user_hndl *handler; | 105 | const struct ipmi_user_hndl *handler; |
106 | void *handler_data; | 106 | void *handler_data; |
107 | 107 | ||
108 | /* The interface this user is bound to. */ | 108 | /* The interface this user is bound to. */ |
@@ -919,7 +919,7 @@ static int intf_err_seq(ipmi_smi_t intf, | |||
919 | 919 | ||
920 | 920 | ||
921 | int ipmi_create_user(unsigned int if_num, | 921 | int ipmi_create_user(unsigned int if_num, |
922 | struct ipmi_user_hndl *handler, | 922 | const struct ipmi_user_hndl *handler, |
923 | void *handler_data, | 923 | void *handler_data, |
924 | ipmi_user_t *user) | 924 | ipmi_user_t *user) |
925 | { | 925 | { |
diff --git a/drivers/char/ipmi/ipmi_powernv.c b/drivers/char/ipmi/ipmi_powernv.c index 6e658aa114f1..b338a4becbf8 100644 --- a/drivers/char/ipmi/ipmi_powernv.c +++ b/drivers/char/ipmi/ipmi_powernv.c | |||
@@ -196,7 +196,7 @@ static void ipmi_powernv_poll(void *send_info) | |||
196 | ipmi_powernv_recv(smi); | 196 | ipmi_powernv_recv(smi); |
197 | } | 197 | } |
198 | 198 | ||
199 | static struct ipmi_smi_handlers ipmi_powernv_smi_handlers = { | 199 | static const struct ipmi_smi_handlers ipmi_powernv_smi_handlers = { |
200 | .owner = THIS_MODULE, | 200 | .owner = THIS_MODULE, |
201 | .start_processing = ipmi_powernv_start_processing, | 201 | .start_processing = ipmi_powernv_start_processing, |
202 | .sender = ipmi_powernv_send, | 202 | .sender = ipmi_powernv_send, |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 4035495f3a86..30b9e83bf1bf 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -985,7 +985,7 @@ static void ipmi_wdog_pretimeout_handler(void *handler_data) | |||
985 | pretimeout_since_last_heartbeat = 1; | 985 | pretimeout_since_last_heartbeat = 1; |
986 | } | 986 | } |
987 | 987 | ||
988 | static struct ipmi_user_hndl ipmi_hndlrs = { | 988 | static const struct ipmi_user_hndl ipmi_hndlrs = { |
989 | .ipmi_recv_hndl = ipmi_wdog_msg_handler, | 989 | .ipmi_recv_hndl = ipmi_wdog_msg_handler, |
990 | .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler | 990 | .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler |
991 | }; | 991 | }; |
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 78c5d5ae3857..f1045b2c6a00 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h | |||
@@ -100,7 +100,7 @@ struct ipmi_user_hndl { | |||
100 | 100 | ||
101 | /* Create a new user of the IPMI layer on the given interface number. */ | 101 | /* Create a new user of the IPMI layer on the given interface number. */ |
102 | int ipmi_create_user(unsigned int if_num, | 102 | int ipmi_create_user(unsigned int if_num, |
103 | struct ipmi_user_hndl *handler, | 103 | const struct ipmi_user_hndl *handler, |
104 | void *handler_data, | 104 | void *handler_data, |
105 | ipmi_user_t *user); | 105 | ipmi_user_t *user); |
106 | 106 | ||