On Wed, Jun 19, 2024 at 7:47 AM Shan-Chun Hung<shanchun1218@xxxxxxxxx> wrote:I will fix it.
This adds the SDHCI driver for the MA35 series SoC. It is based upon theEven I agree with Markus' remarks, so please correct your SoB by using
SDHCI interface, but requires some extra initialization.
Signed-off-by: schung<schung@xxxxxxxxxxx>
something similar to the From line.
I am not familiar with IWYU yet, but I will learn it and use it for checks later on.
...
+config MMC_SDHCI_OF_MA35D1OF is not compile dependency AFAICS, if you want make it functional, use
+ tristate "SDHCI OF support for the MA35D1 SDHCI controller"
+ depends on ARCH_A35 || COMPILE_TEST
+ depends on MMC_SDHCI_PLTFM
+ depends on OF && COMMON_CLK
depends on OF || COMPILE_TEST
...
You are missing a lot of header inclusions, please follow IWYU principle.
+ array_size.hI will add sizes.h and directly apply globally defined ALIGN() macro instead
+ bits.h
+#include <linux/clk.h>+ device.h
+#include <linux/dma-mapping.h>+ err.h
+#include <linux/mfd/syscon.h>+ math.h
+ mod_devicetable.h
+#include <linux/module.h>+ platform_device.h
+#include <linux/mmc/mmc.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regmap.h>+ types.h
+#include <linux/reset.h>
+#include <linux/slab.h>
...
+#define BOUNDARY_OK(addr, len) \Besides sizes.h being missed, this can be done with help of ALIGN()
+ ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
macro (or alike). So, kill this and use the globally defined macro
inline.
...I will fix it.
+ /* If the clock frequency exceeds MMC_HIGH_52_MAX_DTR,/*
+ * disable command conflict check.
+ */
* The comment style is wrong and
* the indentation in the second line.
* Fix it as in this example.
*/
...
I will use fsleep() instead of usleep_range().+static void ma35_voltage_switch(struct sdhci_host *host)Use fsleep()
+{
+ /* Wait for 5ms after set 1.8V signal enable bit */
+ usleep_range(5000, 5500);
I will fix it.+}It's way too big for indentation, moreover it uses an unusual pattern,
+
+static int ma35_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct ma35_priv *priv = sdhci_pltfm_priv(pltfm_host);
+
+ /* Limitations require a reset SD/eMMC before tuning. */
+ if (!IS_ERR(priv->rst)) {
usually we check for an error case first. So, invert the conditional
and this all code will become much better.
Your idea is better, I will change it.+ int idx;sizeof(u32) ?
+ u32 *val;
+
+ val = kmalloc(ARRAY_SIZE(restore_data), GFP_KERNEL);
+ for (idx = 0; idx < ARRAY_SIZE(restore_data); idx++) {
+ if (restore_data[idx].width == 32)
I will fix it.+ val[idx] = sdhci_readl(host, restore_data[idx].reg);sizeof(u8) ?
+ else if (restore_data[idx].width == 8)
I will fix it.+ val[idx] = sdhci_readb(host, restore_data[idx].reg);As per above?
+ }
+
+ reset_control_assert(priv->rst);
+ reset_control_deassert(priv->rst);
+
+ for (idx = 0; idx < ARRAY_SIZE(restore_data); idx++) {
+ if (restore_data[idx].width == 32)
+ sdhci_writel(host, val[idx], restore_data[idx].reg);
+ else if (restore_data[idx].width == 8)
+ sdhci_writeb(host, val[idx], restore_data[idx].reg);
I will use "dev" instead of "&pdev->dev".+ }...
+
+ kfree(val);
+ }
+
+ return sdhci_execute_tuning(mmc, opcode);
+}
+static int ma35_probe(struct platform_device *pdev)Since you have it, use it!
+{
+ struct device *dev = &pdev->dev;
I will fix it.+ struct sdhci_pltfm_host *pltfm_host;One line?
+ struct sdhci_host *host;
+ struct ma35_priv *priv;
+ int err;
+ u32 extra, ctl;
+
+ host = sdhci_pltfm_init(pdev, &sdhci_ma35_pdata,
+ sizeof(struct ma35_priv));
I will fix it.+ if (IS_ERR(host))Wrong comment style.
+ return PTR_ERR(host);
+
+ /*
+ * extra adma table cnt for cross 128M boundary handling.
+ */
I will use min() macro to fix it+ extra = DIV_ROUND_UP_ULL(dma_get_required_mask(&pdev->dev), SZ_128M);min() ? clamp() ?
+ if (extra > SDHCI_MAX_SEGS)
+ extra = SDHCI_MAX_SEGS;
I will remove the "if ..."+ host->adma_table_cnt += extra;Why?
+ pltfm_host = sdhci_priv(host);
+ priv = sdhci_pltfm_priv(pltfm_host);
+ if (dev->of_node) {
I will use dev_err_probe() instead of dev_err()+ pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);Use
+ if (IS_ERR(pltfm_host->clk)) {
+ err = PTR_ERR(pltfm_host->clk);
+ dev_err(&pdev->dev, "failed to get clk: %d\n", err);
return dev_err_probe(...);
I have tested it, there is no error messages during driver initial process.+ goto free_pltfm;This is wrong. You may not call non-devm before devm ones, otherwise
it makes a room for subtle mistakes on remove-probe or unbind-bind
cycles. Have you tested that?
I will use devm_clk_get_optional_enabled() instead.+ }Use _enabled variant of devm_clk_get() instead.
+ err = clk_prepare_enable(pltfm_host->clk);
+ if (err)
+ goto free_pltfm;
I will add an error check.+ }No error check?!
+
+ err = mmc_of_parse(host->mmc);
+ if (err)
+ goto err_clk;
+
+ priv->rst = devm_reset_control_get(&pdev->dev, NULL);
I will fix it.+ sdhci_get_of_property(pdev);dev_of_node(dev)
+
+ priv->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (!IS_ERR(priv->pinctrl)) {
+ priv->pins_default = pinctrl_lookup_state(priv->pinctrl, "default");
+ priv->pins_uhs = pinctrl_lookup_state(priv->pinctrl, "state_uhs");
+ pinctrl_select_state(priv->pinctrl, priv->pins_default);
+ }
+
+ if (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)) {
+ u32 reg;
+
+ priv->regmap = syscon_regmap_lookup_by_phandle(
+ pdev->dev.of_node, "nuvoton,sys");
I will use devm_clk_get_optional_enabled, so I will remove it.+This will go with the _enabled variant being used.
+ if (!IS_ERR(priv->regmap)) {
+ /* Enable SDHCI voltage stable for 1.8V */
+ regmap_read(priv->regmap, MA35_SYS_MISCFCR0, ®);
+ reg |= BIT(17);
+ regmap_write(priv->regmap, MA35_SYS_MISCFCR0, reg);
+ }
+
+ host->mmc_host_ops.start_signal_voltage_switch =
+ ma35_start_signal_voltage_switch;
+ }
+
+ host->mmc_host_ops.execute_tuning = ma35_execute_tuning;
+
+ err = sdhci_add_host(host);
+ if (err)
+ goto err_clk;
+
+ /* Enable INCR16 and INCR8 */
+ ctl = sdhci_readw(host, MA35_SDHCI_MBIUCTL);
+ ctl &= ~MA35_SDHCI_INCR_MSK;
+ ctl |= MA35_SDHCI_INCR16|MA35_SDHCI_INCR8;
+ sdhci_writew(host, ctl, MA35_SDHCI_MBIUCTL);
+
+ return 0;
+err_clk:
+ clk_disable_unprepare(pltfm_host->clk);
+free_pltfm:This should go to be correct in ordering.
+ sdhci_pltfm_free(pdev);
I will fix it.+ return err;Use remove_new callback.
+}
+
+static int ma35_remove(struct platform_device *pdev)
I will use sdhci_pltfm_remove instead of the ma35_remove.+{At least these two will go away as per probe error path.
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ sdhci_remove_host(host, 0);
+ clk_disable_unprepare(pltfm_host->clk);
+ sdhci_pltfm_free(pdev);
I will fix it.+ return 0;...
+}
+MODULE_AUTHOR("shanchun1218@xxxxxxxxxx");Needs to be fixed as Markus said.