1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2019 Nuvoton Technology corporation 3 4 #include <linux/bitfield.h> 5 #include <linux/clk.h> 6 #include <linux/interrupt.h> 7 #include <linux/jiffies.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/peci.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 #include <linux/reset.h> 14 15 /* NPCM GCR module */ 16 #define NPCM_INTCR3_OFFSET 0x9C 17 #define NPCM_INTCR3_PECIVSEL BIT(19) 18 19 /* NPCM PECI Registers */ 20 #define NPCM_PECI_CTL_STS 0x00 21 #define NPCM_PECI_RD_LENGTH 0x04 22 #define NPCM_PECI_ADDR 0x08 23 #define NPCM_PECI_CMD 0x0C 24 #define NPCM_PECI_CTL2 0x10 25 #define NPCM_PECI_WR_LENGTH 0x1C 26 #define NPCM_PECI_PDDR 0x2C 27 #define NPCM_PECI_DAT_INOUT(n) (0x100 + ((n) * 4)) 28 29 #define NPCM_PECI_MAX_REG 0x200 30 31 /* NPCM_PECI_CTL_STS - 0x00 : Control Register */ 32 #define NPCM_PECI_CTRL_DONE_INT_EN BIT(6) 33 #define NPCM_PECI_CTRL_ABRT_ERR BIT(4) 34 #define NPCM_PECI_CTRL_CRC_ERR BIT(3) 35 #define NPCM_PECI_CTRL_DONE BIT(1) 36 #define NPCM_PECI_CTRL_START_BUSY BIT(0) 37 38 /* NPCM_PECI_RD_LENGTH - 0x04 : Command Register */ 39 #define NPCM_PECI_RD_LEN_MASK GENMASK(6, 0) 40 41 /* NPCM_PECI_CMD - 0x10 : Command Register */ 42 #define NPCM_PECI_CTL2_MASK GENMASK(7, 6) 43 44 /* NPCM_PECI_WR_LENGTH - 0x1C : Command Register */ 45 #define NPCM_PECI_WR_LEN_MASK GENMASK(6, 0) 46 47 /* NPCM_PECI_PDDR - 0x2C : Command Register */ 48 #define NPCM_PECI_PDDR_MASK GENMASK(4, 0) 49 50 #define NPCM_PECI_INT_MASK (NPCM_PECI_CTRL_ABRT_ERR | \ 51 NPCM_PECI_CTRL_CRC_ERR | \ 52 NPCM_PECI_CTRL_DONE) 53 54 #define NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC (50 * USEC_PER_MSEC) 55 #define NPCM_PECI_IDLE_CHECK_INTERVAL_USEC (10 * USEC_PER_MSEC) 56 #define NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT 1000 57 #define NPCM_PECI_CMD_TIMEOUT_MS_MAX 60000 58 #define NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT 15 59 #define NPCM_PECI_PULL_DOWN_DEFAULT 0 60 61 struct npcm_peci { 62 u32 cmd_timeout_ms; 63 struct completion xfer_complete; 64 struct regmap *regmap; 65 u32 status; 66 spinlock_t lock; /* to sync completion status handling */ 67 struct peci_controller *controller; 68 struct device *dev; 69 struct clk *clk; 70 int irq; 71 }; 72 73 static int npcm_peci_xfer(struct peci_controller *controller, u8 addr, struct peci_request *req) 74 { 75 struct npcm_peci *priv = dev_get_drvdata(controller->dev.parent); 76 unsigned long timeout = msecs_to_jiffies(priv->cmd_timeout_ms); 77 unsigned int msg_rd; 78 u32 cmd_sts; 79 int i, ret; 80 81 /* Check command sts and bus idle state */ 82 ret = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts, 83 !(cmd_sts & NPCM_PECI_CTRL_START_BUSY), 84 NPCM_PECI_IDLE_CHECK_INTERVAL_USEC, 85 NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC); 86 if (ret) 87 return ret; /* -ETIMEDOUT */ 88 89 spin_lock_irq(&priv->lock); 90 reinit_completion(&priv->xfer_complete); 91 92 regmap_write(priv->regmap, NPCM_PECI_ADDR, addr); 93 regmap_write(priv->regmap, NPCM_PECI_RD_LENGTH, NPCM_PECI_WR_LEN_MASK & req->rx.len); 94 regmap_write(priv->regmap, NPCM_PECI_WR_LENGTH, NPCM_PECI_WR_LEN_MASK & req->tx.len); 95 96 if (req->tx.len) { 97 regmap_write(priv->regmap, NPCM_PECI_CMD, req->tx.buf[0]); 98 99 for (i = 0; i < (req->tx.len - 1); i++) 100 regmap_write(priv->regmap, NPCM_PECI_DAT_INOUT(i), req->tx.buf[i + 1]); 101 } 102 103 #if IS_ENABLED(CONFIG_DYNAMIC_DEBUG) 104 dev_dbg(priv->dev, "addr : %#02x, tx.len : %#02x, rx.len : %#02x\n", 105 addr, req->tx.len, req->rx.len); 106 print_hex_dump_bytes("TX : ", DUMP_PREFIX_NONE, req->tx.buf, req->tx.len); 107 #endif 108 109 priv->status = 0; 110 regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS, NPCM_PECI_CTRL_START_BUSY, 111 NPCM_PECI_CTRL_START_BUSY); 112 113 spin_unlock_irq(&priv->lock); 114 115 ret = wait_for_completion_interruptible_timeout(&priv->xfer_complete, timeout); 116 if (ret < 0) 117 return ret; 118 119 if (ret == 0) { 120 dev_dbg(priv->dev, "timeout waiting for a response\n"); 121 return -ETIMEDOUT; 122 } 123 124 spin_lock_irq(&priv->lock); 125 126 if (priv->status != NPCM_PECI_CTRL_DONE) { 127 spin_unlock_irq(&priv->lock); 128 dev_dbg(priv->dev, "no valid response, status: %#02x\n", priv->status); 129 return -EIO; 130 } 131 132 regmap_write(priv->regmap, NPCM_PECI_CMD, 0); 133 134 for (i = 0; i < req->rx.len; i++) { 135 regmap_read(priv->regmap, NPCM_PECI_DAT_INOUT(i), &msg_rd); 136 req->rx.buf[i] = (u8)msg_rd; 137 } 138 139 spin_unlock_irq(&priv->lock); 140 141 #if IS_ENABLED(CONFIG_DYNAMIC_DEBUG) 142 print_hex_dump_bytes("RX : ", DUMP_PREFIX_NONE, req->rx.buf, req->rx.len); 143 #endif 144 return 0; 145 } 146 147 static irqreturn_t npcm_peci_irq_handler(int irq, void *arg) 148 { 149 struct npcm_peci *priv = arg; 150 u32 status_ack = 0; 151 u32 status; 152 153 spin_lock(&priv->lock); 154 regmap_read(priv->regmap, NPCM_PECI_CTL_STS, &status); 155 priv->status |= (status & NPCM_PECI_INT_MASK); 156 157 if (status & NPCM_PECI_CTRL_CRC_ERR) 158 status_ack |= NPCM_PECI_CTRL_CRC_ERR; 159 160 if (status & NPCM_PECI_CTRL_ABRT_ERR) 161 status_ack |= NPCM_PECI_CTRL_ABRT_ERR; 162 163 /* 164 * All commands should be ended up with a NPCM_PECI_CTRL_DONE 165 * bit set even in an error case. 166 */ 167 if (status & NPCM_PECI_CTRL_DONE) { 168 status_ack |= NPCM_PECI_CTRL_DONE; 169 complete(&priv->xfer_complete); 170 } 171 172 regmap_write_bits(priv->regmap, NPCM_PECI_CTL_STS, NPCM_PECI_INT_MASK, status_ack); 173 174 spin_unlock(&priv->lock); 175 return IRQ_HANDLED; 176 } 177 178 static int npcm_peci_init_ctrl(struct npcm_peci *priv) 179 { 180 u32 cmd_sts; 181 int ret; 182 183 priv->clk = devm_clk_get_enabled(priv->dev, NULL); 184 if (IS_ERR(priv->clk)) { 185 dev_err(priv->dev, "failed to get ref clock\n"); 186 return PTR_ERR(priv->clk); 187 } 188 189 ret = device_property_read_u32(priv->dev, "cmd-timeout-ms", &priv->cmd_timeout_ms); 190 if (ret) { 191 priv->cmd_timeout_ms = NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT; 192 } else if (priv->cmd_timeout_ms > NPCM_PECI_CMD_TIMEOUT_MS_MAX || 193 priv->cmd_timeout_ms == 0) { 194 dev_warn(priv->dev, "invalid cmd-timeout-ms: %u, falling back to: %u\n", 195 priv->cmd_timeout_ms, NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT); 196 197 priv->cmd_timeout_ms = NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT; 198 } 199 200 regmap_update_bits(priv->regmap, NPCM_PECI_CTL2, NPCM_PECI_CTL2_MASK, 201 NPCM_PECI_PULL_DOWN_DEFAULT << 6); 202 203 regmap_update_bits(priv->regmap, NPCM_PECI_PDDR, NPCM_PECI_PDDR_MASK, 204 NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT); 205 206 ret = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts, 207 !(cmd_sts & NPCM_PECI_CTRL_START_BUSY), 208 NPCM_PECI_IDLE_CHECK_INTERVAL_USEC, 209 NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC); 210 if (ret) 211 return ret; /* -ETIMEDOUT */ 212 213 /* PECI interrupt enable */ 214 regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS, NPCM_PECI_CTRL_DONE_INT_EN, 215 NPCM_PECI_CTRL_DONE_INT_EN); 216 217 return 0; 218 } 219 220 static const struct regmap_config npcm_peci_regmap_config = { 221 .reg_bits = 8, 222 .val_bits = 8, 223 .max_register = NPCM_PECI_MAX_REG, 224 .fast_io = true, 225 }; 226 227 static struct peci_controller_ops npcm_ops = { 228 .xfer = npcm_peci_xfer, 229 }; 230 231 static int npcm_peci_probe(struct platform_device *pdev) 232 { 233 struct peci_controller *controller; 234 struct npcm_peci *priv; 235 void __iomem *base; 236 int ret; 237 238 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 239 if (!priv) 240 return -ENOMEM; 241 242 priv->dev = &pdev->dev; 243 dev_set_drvdata(&pdev->dev, priv); 244 245 base = devm_platform_ioremap_resource(pdev, 0); 246 if (IS_ERR(base)) 247 return PTR_ERR(base); 248 249 priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, &npcm_peci_regmap_config); 250 if (IS_ERR(priv->regmap)) 251 return PTR_ERR(priv->regmap); 252 253 priv->irq = platform_get_irq(pdev, 0); 254 if (priv->irq < 0) 255 return priv->irq; 256 257 ret = devm_request_irq(&pdev->dev, priv->irq, npcm_peci_irq_handler, 258 0, "peci-npcm-irq", priv); 259 if (ret) 260 return ret; 261 262 init_completion(&priv->xfer_complete); 263 spin_lock_init(&priv->lock); 264 265 ret = npcm_peci_init_ctrl(priv); 266 if (ret) 267 return ret; 268 269 controller = devm_peci_controller_add(priv->dev, &npcm_ops); 270 if (IS_ERR(controller)) 271 return dev_err_probe(priv->dev, PTR_ERR(controller), 272 "failed to add npcm peci controller\n"); 273 274 priv->controller = controller; 275 276 return 0; 277 } 278 279 static const struct of_device_id npcm_peci_of_table[] = { 280 { .compatible = "nuvoton,npcm750-peci", }, 281 { .compatible = "nuvoton,npcm845-peci", }, 282 { } 283 }; 284 MODULE_DEVICE_TABLE(of, npcm_peci_of_table); 285 286 static struct platform_driver npcm_peci_driver = { 287 .probe = npcm_peci_probe, 288 .driver = { 289 .name = KBUILD_MODNAME, 290 .of_match_table = npcm_peci_of_table, 291 }, 292 }; 293 module_platform_driver(npcm_peci_driver); 294 295 MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>"); 296 MODULE_DESCRIPTION("NPCM PECI driver"); 297 MODULE_LICENSE("GPL"); 298 MODULE_IMPORT_NS(PECI); 299