Lines Matching +full:max +full:- +full:rx +full:- +full:timeout +full:- +full:ms
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2012-2017 ASPEED Technology Inc.
3 // Copyright (c) 2018-2021 Intel Corporation
10 #include <linux/clk-provider.h>
88 /* Rx/Tx Data Buffer Registers */
112 /* Timeout */
144 u32 val = readl(priv->base + ASPEED_PECI_CTRL); in aspeed_peci_controller_enable()
149 writel(val, priv->base + ASPEED_PECI_CTRL); in aspeed_peci_controller_enable()
157 writel(ASPEED_PECI_INT_MASK, priv->base + ASPEED_PECI_INT_STS); in aspeed_peci_init_regs()
162 writel(val, priv->base + ASPEED_PECI_INT_CTRL); in aspeed_peci_init_regs()
165 writel(val, priv->base + ASPEED_PECI_CTRL); in aspeed_peci_init_regs()
170 u32 cmd_sts = readl(priv->base + ASPEED_PECI_CMD); in aspeed_peci_check_idle()
176 * where the hardware is not in idle state - we need to reset and in aspeed_peci_check_idle()
180 ret = reset_control_assert(priv->rst); in aspeed_peci_check_idle()
182 dev_err(priv->dev, "cannot assert reset control\n"); in aspeed_peci_check_idle()
186 ret = reset_control_deassert(priv->rst); in aspeed_peci_check_idle()
188 dev_err(priv->dev, "cannot deassert reset control\n"); in aspeed_peci_check_idle()
194 ret = clk_set_rate(priv->clk, priv->clk_frequency); in aspeed_peci_check_idle()
196 dev_err(priv->dev, "cannot set clock frequency\n"); in aspeed_peci_check_idle()
203 return readl_poll_timeout(priv->base + ASPEED_PECI_CMD, in aspeed_peci_check_idle()
213 struct aspeed_peci *priv = dev_get_drvdata(controller->dev.parent); in aspeed_peci_xfer()
214 unsigned long timeout = msecs_to_jiffies(priv->cmd_timeout_ms); in aspeed_peci_xfer() local
218 if (req->tx.len > ASPEED_PECI_DATA_BUF_SIZE_MAX || in aspeed_peci_xfer()
219 req->rx.len > ASPEED_PECI_DATA_BUF_SIZE_MAX) in aspeed_peci_xfer()
220 return -EINVAL; in aspeed_peci_xfer()
225 return ret; /* -ETIMEDOUT */ in aspeed_peci_xfer()
227 spin_lock_irq(&priv->lock); in aspeed_peci_xfer()
228 reinit_completion(&priv->xfer_complete); in aspeed_peci_xfer()
231 FIELD_PREP(ASPEED_PECI_WR_LEN_MASK, req->tx.len) | in aspeed_peci_xfer()
232 FIELD_PREP(ASPEED_PECI_RD_LEN_MASK, req->rx.len); in aspeed_peci_xfer()
234 writel(peci_head, priv->base + ASPEED_PECI_RW_LENGTH); in aspeed_peci_xfer()
236 for (i = 0; i < req->tx.len; i += 4) { in aspeed_peci_xfer()
239 writel(get_unaligned_le32(&req->tx.buf[i]), priv->base + reg); in aspeed_peci_xfer()
243 dev_dbg(priv->dev, "HEAD : %#08x\n", peci_head); in aspeed_peci_xfer()
244 print_hex_dump_bytes("TX : ", DUMP_PREFIX_NONE, req->tx.buf, req->tx.len); in aspeed_peci_xfer()
247 priv->status = 0; in aspeed_peci_xfer()
248 writel(ASPEED_PECI_CMD_FIRE, priv->base + ASPEED_PECI_CMD); in aspeed_peci_xfer()
249 spin_unlock_irq(&priv->lock); in aspeed_peci_xfer()
251 ret = wait_for_completion_interruptible_timeout(&priv->xfer_complete, timeout); in aspeed_peci_xfer()
256 dev_dbg(priv->dev, "timeout waiting for a response\n"); in aspeed_peci_xfer()
257 return -ETIMEDOUT; in aspeed_peci_xfer()
260 spin_lock_irq(&priv->lock); in aspeed_peci_xfer()
262 if (priv->status != ASPEED_PECI_INT_CMD_DONE) { in aspeed_peci_xfer()
263 spin_unlock_irq(&priv->lock); in aspeed_peci_xfer()
264 dev_dbg(priv->dev, "no valid response, status: %#02x\n", priv->status); in aspeed_peci_xfer()
265 return -EIO; in aspeed_peci_xfer()
268 spin_unlock_irq(&priv->lock); in aspeed_peci_xfer()
272 * buffer size is multiple of 4-bytes. in aspeed_peci_xfer()
276 for (i = 0; i < req->rx.len; i += 4) { in aspeed_peci_xfer()
278 u32 rx_data = readl(priv->base + reg); in aspeed_peci_xfer()
280 put_unaligned_le32(rx_data, &req->rx.buf[i]); in aspeed_peci_xfer()
284 print_hex_dump_bytes("RX : ", DUMP_PREFIX_NONE, req->rx.buf, req->rx.len); in aspeed_peci_xfer()
294 spin_lock(&priv->lock); in aspeed_peci_irq_handler()
295 status = readl(priv->base + ASPEED_PECI_INT_STS); in aspeed_peci_irq_handler()
296 writel(status, priv->base + ASPEED_PECI_INT_STS); in aspeed_peci_irq_handler()
297 priv->status |= (status & ASPEED_PECI_INT_MASK); in aspeed_peci_irq_handler()
304 complete(&priv->xfer_complete); in aspeed_peci_irq_handler()
306 writel(0, priv->base + ASPEED_PECI_CMD); in aspeed_peci_irq_handler()
308 spin_unlock(&priv->lock); in aspeed_peci_irq_handler()
320 diff = abs(rate - ASPEED_PECI_CLK_DIV1(i) * ASPEED_PECI_CLK_DIV2(j)); in clk_aspeed_peci_find_div_values()
346 struct aspeed_peci *aspeed_peci = peci_clk->aspeed_peci; in clk_aspeed_peci_set_rate()
353 val = readl(aspeed_peci->base + ASPEED_PECI_CTRL); in clk_aspeed_peci_set_rate()
356 writel(val, aspeed_peci->base + ASPEED_PECI_CTRL); in clk_aspeed_peci_set_rate()
360 writel(val, aspeed_peci->base + ASPEED_PECI_TIMING_NEGOTIATION); in clk_aspeed_peci_set_rate()
376 struct aspeed_peci *aspeed_peci = peci_clk->aspeed_peci; in clk_aspeed_peci_recalc_rate()
380 reg = readl(aspeed_peci->base + ASPEED_PECI_TIMING_NEGOTIATION); in clk_aspeed_peci_recalc_rate()
387 reg = readl(aspeed_peci->base + ASPEED_PECI_CTRL); in clk_aspeed_peci_recalc_rate()
431 return ERR_PTR(-ENOMEM); in devm_aspeed_peci_register_clk_div()
433 peci_clk->hw.init = &init; in devm_aspeed_peci_register_clk_div()
434 peci_clk->aspeed_peci = priv; in devm_aspeed_peci_register_clk_div()
436 ret = devm_clk_hw_register(dev, &peci_clk->hw); in devm_aspeed_peci_register_clk_div()
440 return peci_clk->hw.clk; in devm_aspeed_peci_register_clk_div()
444 u32 min, u32 max, u32 default_val, u32 *propval) in aspeed_peci_property_sanitize() argument
452 } else if (val > max || val < min) { in aspeed_peci_property_sanitize()
464 aspeed_peci_property_sanitize(priv->dev, "clock-frequency", in aspeed_peci_property_setup()
466 ASPEED_PECI_CLK_FREQUENCY_DEFAULT, &priv->clk_frequency); in aspeed_peci_property_setup()
467 aspeed_peci_property_sanitize(priv->dev, "cmd-timeout-ms", in aspeed_peci_property_setup()
469 ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT, &priv->cmd_timeout_ms); in aspeed_peci_property_setup()
515 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in aspeed_peci_probe()
517 return -ENOMEM; in aspeed_peci_probe()
519 priv->dev = &pdev->dev; in aspeed_peci_probe()
520 dev_set_drvdata(priv->dev, priv); in aspeed_peci_probe()
522 priv->base = devm_platform_ioremap_resource(pdev, 0); in aspeed_peci_probe()
523 if (IS_ERR(priv->base)) in aspeed_peci_probe()
524 return PTR_ERR(priv->base); in aspeed_peci_probe()
526 priv->irq = platform_get_irq(pdev, 0); in aspeed_peci_probe()
527 if (priv->irq < 0) in aspeed_peci_probe()
528 return priv->irq; in aspeed_peci_probe()
530 ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_peci_irq_handler, in aspeed_peci_probe()
531 0, "peci-aspeed", priv); in aspeed_peci_probe()
535 init_completion(&priv->xfer_complete); in aspeed_peci_probe()
536 spin_lock_init(&priv->lock); in aspeed_peci_probe()
538 priv->rst = devm_reset_control_get(&pdev->dev, NULL); in aspeed_peci_probe()
539 if (IS_ERR(priv->rst)) in aspeed_peci_probe()
540 return dev_err_probe(priv->dev, PTR_ERR(priv->rst), in aspeed_peci_probe()
543 ret = devm_aspeed_peci_reset_control_deassert(priv->dev, priv->rst); in aspeed_peci_probe()
545 return dev_err_probe(priv->dev, ret, "cannot deassert reset control\n"); in aspeed_peci_probe()
551 ref_clk = devm_clk_get(priv->dev, NULL); in aspeed_peci_probe()
553 return dev_err_probe(priv->dev, PTR_ERR(ref_clk), "failed to get ref clock\n"); in aspeed_peci_probe()
555 priv->clk = devm_aspeed_peci_register_clk_div(priv->dev, ref_clk, priv); in aspeed_peci_probe()
556 if (IS_ERR(priv->clk)) in aspeed_peci_probe()
557 return dev_err_probe(priv->dev, PTR_ERR(priv->clk), "cannot register clock\n"); in aspeed_peci_probe()
559 ret = clk_set_rate(priv->clk, priv->clk_frequency); in aspeed_peci_probe()
561 return dev_err_probe(priv->dev, ret, "cannot set clock frequency\n"); in aspeed_peci_probe()
563 ret = devm_aspeed_peci_clk_enable(priv->dev, priv->clk); in aspeed_peci_probe()
565 return dev_err_probe(priv->dev, ret, "failed to enable clock\n"); in aspeed_peci_probe()
569 controller = devm_peci_controller_add(priv->dev, &aspeed_ops); in aspeed_peci_probe()
571 return dev_err_probe(priv->dev, PTR_ERR(controller), in aspeed_peci_probe()
574 priv->controller = controller; in aspeed_peci_probe()
580 { .compatible = "aspeed,ast2400-peci", },
581 { .compatible = "aspeed,ast2500-peci", },
582 { .compatible = "aspeed,ast2600-peci", },
590 .name = "peci-aspeed",