0001
0002
0003
0004
0005 #include <asm/unaligned.h>
0006
0007 #include <linux/bitfield.h>
0008 #include <linux/clk.h>
0009 #include <linux/clkdev.h>
0010 #include <linux/clk-provider.h>
0011 #include <linux/delay.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/io.h>
0014 #include <linux/iopoll.h>
0015 #include <linux/jiffies.h>
0016 #include <linux/math.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/peci.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/reset.h>
0022
0023
0024
0025 #define ASPEED_PECI_CTRL 0x00
0026 #define ASPEED_PECI_CTRL_SAMPLING_MASK GENMASK(19, 16)
0027 #define ASPEED_PECI_CTRL_RD_MODE_MASK GENMASK(13, 12)
0028 #define ASPEED_PECI_CTRL_RD_MODE_DBG BIT(13)
0029 #define ASPEED_PECI_CTRL_RD_MODE_COUNT BIT(12)
0030 #define ASPEED_PECI_CTRL_CLK_SRC_HCLK BIT(11)
0031 #define ASPEED_PECI_CTRL_CLK_DIV_MASK GENMASK(10, 8)
0032 #define ASPEED_PECI_CTRL_INVERT_OUT BIT(7)
0033 #define ASPEED_PECI_CTRL_INVERT_IN BIT(6)
0034 #define ASPEED_PECI_CTRL_BUS_CONTENTION_EN BIT(5)
0035 #define ASPEED_PECI_CTRL_PECI_EN BIT(4)
0036 #define ASPEED_PECI_CTRL_PECI_CLK_EN BIT(0)
0037
0038
0039 #define ASPEED_PECI_TIMING_NEGOTIATION 0x04
0040 #define ASPEED_PECI_T_NEGO_MSG_MASK GENMASK(15, 8)
0041 #define ASPEED_PECI_T_NEGO_ADDR_MASK GENMASK(7, 0)
0042
0043
0044 #define ASPEED_PECI_CMD 0x08
0045 #define ASPEED_PECI_CMD_PIN_MONITORING BIT(31)
0046 #define ASPEED_PECI_CMD_STS_MASK GENMASK(27, 24)
0047 #define ASPEED_PECI_CMD_STS_ADDR_T_NEGO 0x3
0048 #define ASPEED_PECI_CMD_IDLE_MASK \
0049 (ASPEED_PECI_CMD_STS_MASK | ASPEED_PECI_CMD_PIN_MONITORING)
0050 #define ASPEED_PECI_CMD_FIRE BIT(0)
0051
0052
0053 #define ASPEED_PECI_RW_LENGTH 0x0c
0054 #define ASPEED_PECI_AW_FCS_EN BIT(31)
0055 #define ASPEED_PECI_RD_LEN_MASK GENMASK(23, 16)
0056 #define ASPEED_PECI_WR_LEN_MASK GENMASK(15, 8)
0057 #define ASPEED_PECI_TARGET_ADDR_MASK GENMASK(7, 0)
0058
0059
0060 #define ASPEED_PECI_EXPECTED_FCS 0x10
0061 #define ASPEED_PECI_EXPECTED_RD_FCS_MASK GENMASK(23, 16)
0062 #define ASPEED_PECI_EXPECTED_AW_FCS_AUTO_MASK GENMASK(15, 8)
0063 #define ASPEED_PECI_EXPECTED_WR_FCS_MASK GENMASK(7, 0)
0064
0065
0066 #define ASPEED_PECI_CAPTURED_FCS 0x14
0067 #define ASPEED_PECI_CAPTURED_RD_FCS_MASK GENMASK(23, 16)
0068 #define ASPEED_PECI_CAPTURED_WR_FCS_MASK GENMASK(7, 0)
0069
0070
0071 #define ASPEED_PECI_INT_CTRL 0x18
0072 #define ASPEED_PECI_TIMING_NEGO_SEL_MASK GENMASK(31, 30)
0073 #define ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO 0
0074 #define ASPEED_PECI_2ND_BIT_OF_ADDR_NEGO 1
0075 #define ASPEED_PECI_MESSAGE_NEGO 2
0076 #define ASPEED_PECI_INT_MASK GENMASK(4, 0)
0077 #define ASPEED_PECI_INT_BUS_TIMEOUT BIT(4)
0078 #define ASPEED_PECI_INT_BUS_CONTENTION BIT(3)
0079 #define ASPEED_PECI_INT_WR_FCS_BAD BIT(2)
0080 #define ASPEED_PECI_INT_WR_FCS_ABORT BIT(1)
0081 #define ASPEED_PECI_INT_CMD_DONE BIT(0)
0082
0083
0084 #define ASPEED_PECI_INT_STS 0x1c
0085 #define ASPEED_PECI_INT_TIMING_RESULT_MASK GENMASK(29, 16)
0086
0087
0088
0089 #define ASPEED_PECI_WR_DATA0 0x20
0090 #define ASPEED_PECI_WR_DATA1 0x24
0091 #define ASPEED_PECI_WR_DATA2 0x28
0092 #define ASPEED_PECI_WR_DATA3 0x2c
0093 #define ASPEED_PECI_RD_DATA0 0x30
0094 #define ASPEED_PECI_RD_DATA1 0x34
0095 #define ASPEED_PECI_RD_DATA2 0x38
0096 #define ASPEED_PECI_RD_DATA3 0x3c
0097 #define ASPEED_PECI_WR_DATA4 0x40
0098 #define ASPEED_PECI_WR_DATA5 0x44
0099 #define ASPEED_PECI_WR_DATA6 0x48
0100 #define ASPEED_PECI_WR_DATA7 0x4c
0101 #define ASPEED_PECI_RD_DATA4 0x50
0102 #define ASPEED_PECI_RD_DATA5 0x54
0103 #define ASPEED_PECI_RD_DATA6 0x58
0104 #define ASPEED_PECI_RD_DATA7 0x5c
0105 #define ASPEED_PECI_DATA_BUF_SIZE_MAX 32
0106
0107
0108 #define ASPEED_PECI_CLK_FREQUENCY_MIN 2000
0109 #define ASPEED_PECI_CLK_FREQUENCY_DEFAULT 1000000
0110 #define ASPEED_PECI_CLK_FREQUENCY_MAX 2000000
0111 #define ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT 8
0112
0113 #define ASPEED_PECI_IDLE_CHECK_TIMEOUT_US (50 * USEC_PER_MSEC)
0114 #define ASPEED_PECI_IDLE_CHECK_INTERVAL_US (10 * USEC_PER_MSEC)
0115 #define ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT 1000
0116 #define ASPEED_PECI_CMD_TIMEOUT_MS_MAX 1000
0117
0118 #define ASPEED_PECI_CLK_DIV1(msg_timing) (4 * (msg_timing) + 1)
0119 #define ASPEED_PECI_CLK_DIV2(clk_div_exp) BIT(clk_div_exp)
0120 #define ASPEED_PECI_CLK_DIV(msg_timing, clk_div_exp) \
0121 (4 * ASPEED_PECI_CLK_DIV1(msg_timing) * ASPEED_PECI_CLK_DIV2(clk_div_exp))
0122
0123 struct aspeed_peci {
0124 struct peci_controller *controller;
0125 struct device *dev;
0126 void __iomem *base;
0127 struct reset_control *rst;
0128 int irq;
0129 spinlock_t lock;
0130 struct completion xfer_complete;
0131 struct clk *clk;
0132 u32 clk_frequency;
0133 u32 status;
0134 u32 cmd_timeout_ms;
0135 };
0136
0137 struct clk_aspeed_peci {
0138 struct clk_hw hw;
0139 struct aspeed_peci *aspeed_peci;
0140 };
0141
0142 static void aspeed_peci_controller_enable(struct aspeed_peci *priv)
0143 {
0144 u32 val = readl(priv->base + ASPEED_PECI_CTRL);
0145
0146 val |= ASPEED_PECI_CTRL_PECI_CLK_EN;
0147 val |= ASPEED_PECI_CTRL_PECI_EN;
0148
0149 writel(val, priv->base + ASPEED_PECI_CTRL);
0150 }
0151
0152 static void aspeed_peci_init_regs(struct aspeed_peci *priv)
0153 {
0154 u32 val;
0155
0156
0157 writel(ASPEED_PECI_INT_MASK, priv->base + ASPEED_PECI_INT_STS);
0158
0159
0160 val = FIELD_PREP(ASPEED_PECI_TIMING_NEGO_SEL_MASK, ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO);
0161 val |= ASPEED_PECI_INT_MASK;
0162 writel(val, priv->base + ASPEED_PECI_INT_CTRL);
0163
0164 val = FIELD_PREP(ASPEED_PECI_CTRL_SAMPLING_MASK, ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT);
0165 writel(val, priv->base + ASPEED_PECI_CTRL);
0166 }
0167
0168 static int aspeed_peci_check_idle(struct aspeed_peci *priv)
0169 {
0170 u32 cmd_sts = readl(priv->base + ASPEED_PECI_CMD);
0171 int ret;
0172
0173
0174
0175
0176
0177
0178
0179 if (FIELD_GET(ASPEED_PECI_CMD_STS_MASK, cmd_sts)) {
0180 ret = reset_control_assert(priv->rst);
0181 if (ret) {
0182 dev_err(priv->dev, "cannot assert reset control\n");
0183 return ret;
0184 }
0185
0186 ret = reset_control_deassert(priv->rst);
0187 if (ret) {
0188 dev_err(priv->dev, "cannot deassert reset control\n");
0189 return ret;
0190 }
0191
0192 aspeed_peci_init_regs(priv);
0193
0194 ret = clk_set_rate(priv->clk, priv->clk_frequency);
0195 if (ret < 0) {
0196 dev_err(priv->dev, "cannot set clock frequency\n");
0197 return ret;
0198 }
0199
0200 aspeed_peci_controller_enable(priv);
0201 }
0202
0203 return readl_poll_timeout(priv->base + ASPEED_PECI_CMD,
0204 cmd_sts,
0205 !(cmd_sts & ASPEED_PECI_CMD_IDLE_MASK),
0206 ASPEED_PECI_IDLE_CHECK_INTERVAL_US,
0207 ASPEED_PECI_IDLE_CHECK_TIMEOUT_US);
0208 }
0209
0210 static int aspeed_peci_xfer(struct peci_controller *controller,
0211 u8 addr, struct peci_request *req)
0212 {
0213 struct aspeed_peci *priv = dev_get_drvdata(controller->dev.parent);
0214 unsigned long timeout = msecs_to_jiffies(priv->cmd_timeout_ms);
0215 u32 peci_head;
0216 int ret, i;
0217
0218 if (req->tx.len > ASPEED_PECI_DATA_BUF_SIZE_MAX ||
0219 req->rx.len > ASPEED_PECI_DATA_BUF_SIZE_MAX)
0220 return -EINVAL;
0221
0222
0223 ret = aspeed_peci_check_idle(priv);
0224 if (ret)
0225 return ret;
0226
0227 spin_lock_irq(&priv->lock);
0228 reinit_completion(&priv->xfer_complete);
0229
0230 peci_head = FIELD_PREP(ASPEED_PECI_TARGET_ADDR_MASK, addr) |
0231 FIELD_PREP(ASPEED_PECI_WR_LEN_MASK, req->tx.len) |
0232 FIELD_PREP(ASPEED_PECI_RD_LEN_MASK, req->rx.len);
0233
0234 writel(peci_head, priv->base + ASPEED_PECI_RW_LENGTH);
0235
0236 for (i = 0; i < req->tx.len; i += 4) {
0237 u32 reg = (i < 16 ? ASPEED_PECI_WR_DATA0 : ASPEED_PECI_WR_DATA4) + i % 16;
0238
0239 writel(get_unaligned_le32(&req->tx.buf[i]), priv->base + reg);
0240 }
0241
0242 #if IS_ENABLED(CONFIG_DYNAMIC_DEBUG)
0243 dev_dbg(priv->dev, "HEAD : %#08x\n", peci_head);
0244 print_hex_dump_bytes("TX : ", DUMP_PREFIX_NONE, req->tx.buf, req->tx.len);
0245 #endif
0246
0247 priv->status = 0;
0248 writel(ASPEED_PECI_CMD_FIRE, priv->base + ASPEED_PECI_CMD);
0249 spin_unlock_irq(&priv->lock);
0250
0251 ret = wait_for_completion_interruptible_timeout(&priv->xfer_complete, timeout);
0252 if (ret < 0)
0253 return ret;
0254
0255 if (ret == 0) {
0256 dev_dbg(priv->dev, "timeout waiting for a response\n");
0257 return -ETIMEDOUT;
0258 }
0259
0260 spin_lock_irq(&priv->lock);
0261
0262 if (priv->status != ASPEED_PECI_INT_CMD_DONE) {
0263 spin_unlock_irq(&priv->lock);
0264 dev_dbg(priv->dev, "no valid response, status: %#02x\n", priv->status);
0265 return -EIO;
0266 }
0267
0268 spin_unlock_irq(&priv->lock);
0269
0270
0271
0272
0273
0274 BUILD_BUG_ON(PECI_REQUEST_MAX_BUF_SIZE % 4);
0275
0276 for (i = 0; i < req->rx.len; i += 4) {
0277 u32 reg = (i < 16 ? ASPEED_PECI_RD_DATA0 : ASPEED_PECI_RD_DATA4) + i % 16;
0278 u32 rx_data = readl(priv->base + reg);
0279
0280 put_unaligned_le32(rx_data, &req->rx.buf[i]);
0281 }
0282
0283 #if IS_ENABLED(CONFIG_DYNAMIC_DEBUG)
0284 print_hex_dump_bytes("RX : ", DUMP_PREFIX_NONE, req->rx.buf, req->rx.len);
0285 #endif
0286 return 0;
0287 }
0288
0289 static irqreturn_t aspeed_peci_irq_handler(int irq, void *arg)
0290 {
0291 struct aspeed_peci *priv = arg;
0292 u32 status;
0293
0294 spin_lock(&priv->lock);
0295 status = readl(priv->base + ASPEED_PECI_INT_STS);
0296 writel(status, priv->base + ASPEED_PECI_INT_STS);
0297 priv->status |= (status & ASPEED_PECI_INT_MASK);
0298
0299
0300
0301
0302
0303 if (status & ASPEED_PECI_INT_CMD_DONE)
0304 complete(&priv->xfer_complete);
0305
0306 writel(0, priv->base + ASPEED_PECI_CMD);
0307
0308 spin_unlock(&priv->lock);
0309
0310 return IRQ_HANDLED;
0311 }
0312
0313 static void clk_aspeed_peci_find_div_values(unsigned long rate, int *msg_timing, int *clk_div_exp)
0314 {
0315 unsigned long best_diff = ~0ul, diff;
0316 int msg_timing_temp, clk_div_exp_temp, i, j;
0317
0318 for (i = 1; i <= 255; i++)
0319 for (j = 0; j < 8; j++) {
0320 diff = abs(rate - ASPEED_PECI_CLK_DIV1(i) * ASPEED_PECI_CLK_DIV2(j));
0321 if (diff < best_diff) {
0322 msg_timing_temp = i;
0323 clk_div_exp_temp = j;
0324 best_diff = diff;
0325 }
0326 }
0327
0328 *msg_timing = msg_timing_temp;
0329 *clk_div_exp = clk_div_exp_temp;
0330 }
0331
0332 static int clk_aspeed_peci_get_div(unsigned long rate, const unsigned long *prate)
0333 {
0334 unsigned long this_rate = *prate / (4 * rate);
0335 int msg_timing, clk_div_exp;
0336
0337 clk_aspeed_peci_find_div_values(this_rate, &msg_timing, &clk_div_exp);
0338
0339 return ASPEED_PECI_CLK_DIV(msg_timing, clk_div_exp);
0340 }
0341
0342 static int clk_aspeed_peci_set_rate(struct clk_hw *hw, unsigned long rate,
0343 unsigned long prate)
0344 {
0345 struct clk_aspeed_peci *peci_clk = container_of(hw, struct clk_aspeed_peci, hw);
0346 struct aspeed_peci *aspeed_peci = peci_clk->aspeed_peci;
0347 unsigned long this_rate = prate / (4 * rate);
0348 int clk_div_exp, msg_timing;
0349 u32 val;
0350
0351 clk_aspeed_peci_find_div_values(this_rate, &msg_timing, &clk_div_exp);
0352
0353 val = readl(aspeed_peci->base + ASPEED_PECI_CTRL);
0354 val |= FIELD_PREP(ASPEED_PECI_CTRL_CLK_DIV_MASK, clk_div_exp);
0355 writel(val, aspeed_peci->base + ASPEED_PECI_CTRL);
0356
0357 val = FIELD_PREP(ASPEED_PECI_T_NEGO_MSG_MASK, msg_timing);
0358 val |= FIELD_PREP(ASPEED_PECI_T_NEGO_ADDR_MASK, msg_timing);
0359 writel(val, aspeed_peci->base + ASPEED_PECI_TIMING_NEGOTIATION);
0360
0361 return 0;
0362 }
0363
0364 static long clk_aspeed_peci_round_rate(struct clk_hw *hw, unsigned long rate,
0365 unsigned long *prate)
0366 {
0367 int div = clk_aspeed_peci_get_div(rate, prate);
0368
0369 return DIV_ROUND_UP_ULL(*prate, div);
0370 }
0371
0372 static unsigned long clk_aspeed_peci_recalc_rate(struct clk_hw *hw, unsigned long prate)
0373 {
0374 struct clk_aspeed_peci *peci_clk = container_of(hw, struct clk_aspeed_peci, hw);
0375 struct aspeed_peci *aspeed_peci = peci_clk->aspeed_peci;
0376 int div, msg_timing, addr_timing, clk_div_exp;
0377 u32 reg;
0378
0379 reg = readl(aspeed_peci->base + ASPEED_PECI_TIMING_NEGOTIATION);
0380 msg_timing = FIELD_GET(ASPEED_PECI_T_NEGO_MSG_MASK, reg);
0381 addr_timing = FIELD_GET(ASPEED_PECI_T_NEGO_ADDR_MASK, reg);
0382
0383 if (msg_timing != addr_timing)
0384 return 0;
0385
0386 reg = readl(aspeed_peci->base + ASPEED_PECI_CTRL);
0387 clk_div_exp = FIELD_GET(ASPEED_PECI_CTRL_CLK_DIV_MASK, reg);
0388
0389 div = ASPEED_PECI_CLK_DIV(msg_timing, clk_div_exp);
0390
0391 return DIV_ROUND_UP_ULL(prate, div);
0392 }
0393
0394 static const struct clk_ops clk_aspeed_peci_ops = {
0395 .set_rate = clk_aspeed_peci_set_rate,
0396 .round_rate = clk_aspeed_peci_round_rate,
0397 .recalc_rate = clk_aspeed_peci_recalc_rate,
0398 };
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409 static struct clk *devm_aspeed_peci_register_clk_div(struct device *dev, struct clk *parent,
0410 struct aspeed_peci *priv)
0411 {
0412 struct clk_aspeed_peci *peci_clk;
0413 struct clk_init_data init;
0414 const char *parent_name;
0415 char name[32];
0416 int ret;
0417
0418 snprintf(name, sizeof(name), "%s_div", dev_name(dev));
0419
0420 parent_name = __clk_get_name(parent);
0421
0422 init.ops = &clk_aspeed_peci_ops;
0423 init.name = name;
0424 init.parent_names = (const char* []) { parent_name };
0425 init.num_parents = 1;
0426 init.flags = 0;
0427
0428 peci_clk = devm_kzalloc(dev, sizeof(struct clk_aspeed_peci), GFP_KERNEL);
0429 if (!peci_clk)
0430 return ERR_PTR(-ENOMEM);
0431
0432 peci_clk->hw.init = &init;
0433 peci_clk->aspeed_peci = priv;
0434
0435 ret = devm_clk_hw_register(dev, &peci_clk->hw);
0436 if (ret)
0437 return ERR_PTR(ret);
0438
0439 return peci_clk->hw.clk;
0440 }
0441
0442 static void aspeed_peci_property_sanitize(struct device *dev, const char *propname,
0443 u32 min, u32 max, u32 default_val, u32 *propval)
0444 {
0445 u32 val;
0446 int ret;
0447
0448 ret = device_property_read_u32(dev, propname, &val);
0449 if (ret) {
0450 val = default_val;
0451 } else if (val > max || val < min) {
0452 dev_warn(dev, "invalid %s: %u, falling back to: %u\n",
0453 propname, val, default_val);
0454
0455 val = default_val;
0456 }
0457
0458 *propval = val;
0459 }
0460
0461 static void aspeed_peci_property_setup(struct aspeed_peci *priv)
0462 {
0463 aspeed_peci_property_sanitize(priv->dev, "clock-frequency",
0464 ASPEED_PECI_CLK_FREQUENCY_MIN, ASPEED_PECI_CLK_FREQUENCY_MAX,
0465 ASPEED_PECI_CLK_FREQUENCY_DEFAULT, &priv->clk_frequency);
0466 aspeed_peci_property_sanitize(priv->dev, "cmd-timeout-ms",
0467 1, ASPEED_PECI_CMD_TIMEOUT_MS_MAX,
0468 ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT, &priv->cmd_timeout_ms);
0469 }
0470
0471 static struct peci_controller_ops aspeed_ops = {
0472 .xfer = aspeed_peci_xfer,
0473 };
0474
0475 static void aspeed_peci_reset_control_release(void *data)
0476 {
0477 reset_control_assert(data);
0478 }
0479
0480 static int devm_aspeed_peci_reset_control_deassert(struct device *dev, struct reset_control *rst)
0481 {
0482 int ret;
0483
0484 ret = reset_control_deassert(rst);
0485 if (ret)
0486 return ret;
0487
0488 return devm_add_action_or_reset(dev, aspeed_peci_reset_control_release, rst);
0489 }
0490
0491 static void aspeed_peci_clk_release(void *data)
0492 {
0493 clk_disable_unprepare(data);
0494 }
0495
0496 static int devm_aspeed_peci_clk_enable(struct device *dev, struct clk *clk)
0497 {
0498 int ret;
0499
0500 ret = clk_prepare_enable(clk);
0501 if (ret)
0502 return ret;
0503
0504 return devm_add_action_or_reset(dev, aspeed_peci_clk_release, clk);
0505 }
0506
0507 static int aspeed_peci_probe(struct platform_device *pdev)
0508 {
0509 struct peci_controller *controller;
0510 struct aspeed_peci *priv;
0511 struct clk *ref_clk;
0512 int ret;
0513
0514 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0515 if (!priv)
0516 return -ENOMEM;
0517
0518 priv->dev = &pdev->dev;
0519 dev_set_drvdata(priv->dev, priv);
0520
0521 priv->base = devm_platform_ioremap_resource(pdev, 0);
0522 if (IS_ERR(priv->base))
0523 return PTR_ERR(priv->base);
0524
0525 priv->irq = platform_get_irq(pdev, 0);
0526 if (priv->irq < 0)
0527 return priv->irq;
0528
0529 ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_peci_irq_handler,
0530 0, "peci-aspeed", priv);
0531 if (ret)
0532 return ret;
0533
0534 init_completion(&priv->xfer_complete);
0535 spin_lock_init(&priv->lock);
0536
0537 priv->rst = devm_reset_control_get(&pdev->dev, NULL);
0538 if (IS_ERR(priv->rst))
0539 return dev_err_probe(priv->dev, PTR_ERR(priv->rst),
0540 "failed to get reset control\n");
0541
0542 ret = devm_aspeed_peci_reset_control_deassert(priv->dev, priv->rst);
0543 if (ret)
0544 return dev_err_probe(priv->dev, ret, "cannot deassert reset control\n");
0545
0546 aspeed_peci_property_setup(priv);
0547
0548 aspeed_peci_init_regs(priv);
0549
0550 ref_clk = devm_clk_get(priv->dev, NULL);
0551 if (IS_ERR(ref_clk))
0552 return dev_err_probe(priv->dev, PTR_ERR(ref_clk), "failed to get ref clock\n");
0553
0554 priv->clk = devm_aspeed_peci_register_clk_div(priv->dev, ref_clk, priv);
0555 if (IS_ERR(priv->clk))
0556 return dev_err_probe(priv->dev, PTR_ERR(priv->clk), "cannot register clock\n");
0557
0558 ret = clk_set_rate(priv->clk, priv->clk_frequency);
0559 if (ret < 0)
0560 return dev_err_probe(priv->dev, ret, "cannot set clock frequency\n");
0561
0562 ret = devm_aspeed_peci_clk_enable(priv->dev, priv->clk);
0563 if (ret)
0564 return dev_err_probe(priv->dev, ret, "failed to enable clock\n");
0565
0566 aspeed_peci_controller_enable(priv);
0567
0568 controller = devm_peci_controller_add(priv->dev, &aspeed_ops);
0569 if (IS_ERR(controller))
0570 return dev_err_probe(priv->dev, PTR_ERR(controller),
0571 "failed to add aspeed peci controller\n");
0572
0573 priv->controller = controller;
0574
0575 return 0;
0576 }
0577
0578 static const struct of_device_id aspeed_peci_of_table[] = {
0579 { .compatible = "aspeed,ast2400-peci", },
0580 { .compatible = "aspeed,ast2500-peci", },
0581 { .compatible = "aspeed,ast2600-peci", },
0582 { }
0583 };
0584 MODULE_DEVICE_TABLE(of, aspeed_peci_of_table);
0585
0586 static struct platform_driver aspeed_peci_driver = {
0587 .probe = aspeed_peci_probe,
0588 .driver = {
0589 .name = "peci-aspeed",
0590 .of_match_table = aspeed_peci_of_table,
0591 },
0592 };
0593 module_platform_driver(aspeed_peci_driver);
0594
0595 MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
0596 MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
0597 MODULE_DESCRIPTION("ASPEED PECI driver");
0598 MODULE_LICENSE("GPL");
0599 MODULE_IMPORT_NS(PECI);