1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2015-2018, Intel Corporation. 4 */ 5 6 #define pr_fmt(fmt) "aspeed-kcs-bmc: " fmt 7 8 #include <linux/atomic.h> 9 #include <linux/errno.h> 10 #include <linux/interrupt.h> 11 #include <linux/io.h> 12 #include <linux/mfd/syscon.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/poll.h> 17 #include <linux/regmap.h> 18 #include <linux/sched.h> 19 #include <linux/slab.h> 20 #include <linux/timer.h> 21 22 #include "kcs_bmc.h" 23 24 25 #define DEVICE_NAME "ast-kcs-bmc" 26 27 #define KCS_CHANNEL_MAX 4 28 29 /* mapped to lpc-bmc@0 IO space */ 30 #define LPC_HICR0 0x000 31 #define LPC_HICR0_LPC3E BIT(7) 32 #define LPC_HICR0_LPC2E BIT(6) 33 #define LPC_HICR0_LPC1E BIT(5) 34 #define LPC_HICR2 0x008 35 #define LPC_HICR2_IBFIF3 BIT(3) 36 #define LPC_HICR2_IBFIF2 BIT(2) 37 #define LPC_HICR2_IBFIF1 BIT(1) 38 #define LPC_HICR4 0x010 39 #define LPC_HICR4_LADR12AS BIT(7) 40 #define LPC_HICR4_KCSENBL BIT(2) 41 #define LPC_LADR3H 0x014 42 #define LPC_LADR3L 0x018 43 #define LPC_LADR12H 0x01C 44 #define LPC_LADR12L 0x020 45 #define LPC_IDR1 0x024 46 #define LPC_IDR2 0x028 47 #define LPC_IDR3 0x02C 48 #define LPC_ODR1 0x030 49 #define LPC_ODR2 0x034 50 #define LPC_ODR3 0x038 51 #define LPC_STR1 0x03C 52 #define LPC_STR2 0x040 53 #define LPC_STR3 0x044 54 55 /* mapped to lpc-host@80 IO space */ 56 #define LPC_HICRB 0x080 57 #define LPC_HICRB_IBFIF4 BIT(1) 58 #define LPC_HICRB_LPC4E BIT(0) 59 #define LPC_LADR4 0x090 60 #define LPC_IDR4 0x094 61 #define LPC_ODR4 0x098 62 #define LPC_STR4 0x09C 63 64 struct aspeed_kcs_bmc { 65 struct regmap *map; 66 }; 67 68 69 static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) 70 { 71 struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); 72 u32 val = 0; 73 int rc; 74 75 rc = regmap_read(priv->map, reg, &val); 76 WARN(rc != 0, "regmap_read() failed: %d\n", rc); 77 78 return rc == 0 ? (u8) val : 0; 79 } 80 81 static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) 82 { 83 struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); 84 int rc; 85 86 rc = regmap_write(priv->map, reg, data); 87 WARN(rc != 0, "regmap_write() failed: %d\n", rc); 88 } 89 90 91 /* 92 * AST_usrGuide_KCS.pdf 93 * 2. Background: 94 * we note D for Data, and C for Cmd/Status, default rules are 95 * A. KCS1 / KCS2 ( D / C:X / X+4 ) 96 * D / C : CA0h / CA4h 97 * D / C : CA8h / CACh 98 * B. KCS3 ( D / C:XX2h / XX3h ) 99 * D / C : CA2h / CA3h 100 * D / C : CB2h / CB3h 101 * C. KCS4 102 * D / C : CA4h / CA5h 103 */ 104 static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) 105 { 106 struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); 107 108 switch (kcs_bmc->channel) { 109 case 1: 110 regmap_update_bits(priv->map, LPC_HICR4, 111 LPC_HICR4_LADR12AS, 0); 112 regmap_write(priv->map, LPC_LADR12H, addr >> 8); 113 regmap_write(priv->map, LPC_LADR12L, addr & 0xFF); 114 break; 115 116 case 2: 117 regmap_update_bits(priv->map, LPC_HICR4, 118 LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS); 119 regmap_write(priv->map, LPC_LADR12H, addr >> 8); 120 regmap_write(priv->map, LPC_LADR12L, addr & 0xFF); 121 break; 122 123 case 3: 124 regmap_write(priv->map, LPC_LADR3H, addr >> 8); 125 regmap_write(priv->map, LPC_LADR3L, addr & 0xFF); 126 break; 127 128 case 4: 129 regmap_write(priv->map, LPC_LADR4, ((addr + 1) << 16) | 130 addr); 131 break; 132 133 default: 134 break; 135 } 136 } 137 138 static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) 139 { 140 struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); 141 142 switch (kcs_bmc->channel) { 143 case 1: 144 if (enable) { 145 regmap_update_bits(priv->map, LPC_HICR2, 146 LPC_HICR2_IBFIF1, LPC_HICR2_IBFIF1); 147 regmap_update_bits(priv->map, LPC_HICR0, 148 LPC_HICR0_LPC1E, LPC_HICR0_LPC1E); 149 } else { 150 regmap_update_bits(priv->map, LPC_HICR0, 151 LPC_HICR0_LPC1E, 0); 152 regmap_update_bits(priv->map, LPC_HICR2, 153 LPC_HICR2_IBFIF1, 0); 154 } 155 break; 156 157 case 2: 158 if (enable) { 159 regmap_update_bits(priv->map, LPC_HICR2, 160 LPC_HICR2_IBFIF2, LPC_HICR2_IBFIF2); 161 regmap_update_bits(priv->map, LPC_HICR0, 162 LPC_HICR0_LPC2E, LPC_HICR0_LPC2E); 163 } else { 164 regmap_update_bits(priv->map, LPC_HICR0, 165 LPC_HICR0_LPC2E, 0); 166 regmap_update_bits(priv->map, LPC_HICR2, 167 LPC_HICR2_IBFIF2, 0); 168 } 169 break; 170 171 case 3: 172 if (enable) { 173 regmap_update_bits(priv->map, LPC_HICR2, 174 LPC_HICR2_IBFIF3, LPC_HICR2_IBFIF3); 175 regmap_update_bits(priv->map, LPC_HICR0, 176 LPC_HICR0_LPC3E, LPC_HICR0_LPC3E); 177 regmap_update_bits(priv->map, LPC_HICR4, 178 LPC_HICR4_KCSENBL, LPC_HICR4_KCSENBL); 179 } else { 180 regmap_update_bits(priv->map, LPC_HICR0, 181 LPC_HICR0_LPC3E, 0); 182 regmap_update_bits(priv->map, LPC_HICR4, 183 LPC_HICR4_KCSENBL, 0); 184 regmap_update_bits(priv->map, LPC_HICR2, 185 LPC_HICR2_IBFIF3, 0); 186 } 187 break; 188 189 case 4: 190 if (enable) 191 regmap_update_bits(priv->map, LPC_HICRB, 192 LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E, 193 LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E); 194 else 195 regmap_update_bits(priv->map, LPC_HICRB, 196 LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E, 197 0); 198 break; 199 200 default: 201 break; 202 } 203 } 204 205 static irqreturn_t aspeed_kcs_irq(int irq, void *arg) 206 { 207 struct kcs_bmc *kcs_bmc = arg; 208 209 if (!kcs_bmc_handle_event(kcs_bmc)) 210 return IRQ_HANDLED; 211 212 return IRQ_NONE; 213 } 214 215 static int aspeed_kcs_config_irq(struct kcs_bmc *kcs_bmc, 216 struct platform_device *pdev) 217 { 218 struct device *dev = &pdev->dev; 219 int irq; 220 221 irq = platform_get_irq(pdev, 0); 222 if (irq < 0) 223 return irq; 224 225 return devm_request_irq(dev, irq, aspeed_kcs_irq, IRQF_SHARED, 226 dev_name(dev), kcs_bmc); 227 } 228 229 static const struct kcs_ioreg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = { 230 { .idr = LPC_IDR1, .odr = LPC_ODR1, .str = LPC_STR1 }, 231 { .idr = LPC_IDR2, .odr = LPC_ODR2, .str = LPC_STR2 }, 232 { .idr = LPC_IDR3, .odr = LPC_ODR3, .str = LPC_STR3 }, 233 { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 }, 234 }; 235 236 static int aspeed_kcs_probe(struct platform_device *pdev) 237 { 238 struct device *dev = &pdev->dev; 239 struct aspeed_kcs_bmc *priv; 240 struct kcs_bmc *kcs_bmc; 241 u32 chan, addr; 242 int rc; 243 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; 248 } 249 250 rc = of_property_read_u32(dev->of_node, "kcs_addr", &addr); 251 if (rc) { 252 dev_err(dev, "no valid 'kcs_addr' configured\n"); 253 return -ENODEV; 254 } 255 256 kcs_bmc = kcs_bmc_alloc(dev, sizeof(*priv), chan); 257 if (!kcs_bmc) 258 return -ENOMEM; 259 260 priv = kcs_bmc_priv(kcs_bmc); 261 priv->map = syscon_node_to_regmap(dev->parent->of_node); 262 if (IS_ERR(priv->map)) { 263 dev_err(dev, "Couldn't get regmap\n"); 264 return -ENODEV; 265 } 266 267 kcs_bmc->ioreg = ast_kcs_bmc_ioregs[chan - 1]; 268 kcs_bmc->io_inputb = aspeed_kcs_inb; 269 kcs_bmc->io_outputb = aspeed_kcs_outb; 270 271 dev_set_drvdata(dev, kcs_bmc); 272 273 aspeed_kcs_set_address(kcs_bmc, addr); 274 aspeed_kcs_enable_channel(kcs_bmc, true); 275 rc = aspeed_kcs_config_irq(kcs_bmc, pdev); 276 if (rc) 277 return rc; 278 279 rc = misc_register(&kcs_bmc->miscdev); 280 if (rc) { 281 dev_err(dev, "Unable to register device\n"); 282 return rc; 283 } 284 285 pr_info("channel=%u addr=0x%x idr=0x%x odr=0x%x str=0x%x\n", 286 chan, addr, 287 kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str); 288 289 return 0; 290 } 291 292 static int aspeed_kcs_remove(struct platform_device *pdev) 293 { 294 struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev); 295 296 misc_deregister(&kcs_bmc->miscdev); 297 298 return 0; 299 } 300 301 static const struct of_device_id ast_kcs_bmc_match[] = { 302 { .compatible = "aspeed,ast2400-kcs-bmc" }, 303 { .compatible = "aspeed,ast2500-kcs-bmc" }, 304 { } 305 }; 306 MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match); 307 308 static struct platform_driver ast_kcs_bmc_driver = { 309 .driver = { 310 .name = DEVICE_NAME, 311 .of_match_table = ast_kcs_bmc_match, 312 }, 313 .probe = aspeed_kcs_probe, 314 .remove = aspeed_kcs_remove, 315 }; 316 module_platform_driver(ast_kcs_bmc_driver); 317 318 MODULE_LICENSE("GPL v2"); 319 MODULE_AUTHOR("Haiyue Wang <haiyue.wang@linux.intel.com>"); 320 MODULE_DESCRIPTION("Aspeed device interface to the KCS BMC device"); 321