Thread (1 message) 1 message, 1 author, 2016-11-30

Re: [PATCH v2 2/2] mtd: spi-nor: add rockchip serial flash controller driver

From: Marek Vasut <hidden>
Date: 2016-11-30 03:23:36
Also in: linux-rockchip

On 11/30/2016 02:17 AM, Shawn Lin wrote:
[...]
quoted
quoted
+static inline int rockchip_sfc_pio_read(struct rockchip_sfc *sfc,
u_char *buf,
+                    size_t len)
+{
+    u32 dwords, rx_wl, count, i, tmp;
+    unsigned long timeout;
+    int ret = 0;
+    u32 *tbuf = (u32 *)buf;
+    u_char *tbuf2;
+
+    /*
+     * Align bytes to dwords, and get the remained bytes.
+     * We should always round down to DWORD as the ahb for
+     * Rockchip Socs won't support non-aligned-to-DWORD transfer.
+     * So please don't use any APIs that will finally use non-aligned
+     * read, for instance, memcpy_fromio or ioread32_rep etc.
+     */
+    dwords = len >> 2;
+    len = len & 0x3;
Won't this overwrite some bits past the $buf if you write more than $len
bytes into this memory location ?
I can't see the possibility here to overwrite $buf, no?
Looking at the code again, I believe not, although it's quite
non-trivial piece of code.
quoted
quoted
+    while (dwords) {
+        rx_wl = (readl_relaxed(sfc->regbase + SFC_FSR) >>
+             SFC_FSR_RX_WATER_LVL_SHIFT) &
+             SFC_FSR_RX_WATER_LVL_MASK;
+
+        if (rx_wl > 0) {
+            count = min_t(u32, dwords, rx_wl);
+            for (i = 0; i < count; i++) {
+                *tbuf++ = readl_relaxed(sfc->regbase +
+                            SFC_DATA);
+                dwords--;
+            }
+
+            if (dwords == 0)
+                break;
+            timeout = 0;
+        } else {
+            mdelay(1);
+            if (timeout++ > SFC_MAX_IDLE_RETRY) {
+                ret = -ETIMEDOUT;
+                break;
+            }
+        }
+    }
+
+    if (ret)
+        return ret;
+
+    /* Read the remained bytes */
+    timeout = 0;
+    tbuf2 = (u_char *)tbuf;
+    while (len) {
+        rx_wl = (readl_relaxed(sfc->regbase + SFC_FSR) >>
+             SFC_FSR_RX_WATER_LVL_SHIFT) &
+             SFC_FSR_RX_WATER_LVL_MASK;
+        if (rx_wl > 0) {
+            tmp = readl_relaxed(sfc->regbase + SFC_DATA);
+            for (i = 0; i < len; i++)
+                tbuf2[i] = (u8)((tmp >> (i * 8)) & 0xff);
+            goto done;
+        } else {
+            mdelay(1);
+            if (timeout++ > SFC_MAX_IDLE_RETRY) {
+                ret = -ETIMEDOUT;
+                break;
+            }
+        }
+    }
[...]
quoted
quoted
+static int rockchip_sfc_probe(struct platform_device *pdev)
+{
+    struct device *dev = &pdev->dev;
+    struct resource *res;
+    struct rockchip_sfc *sfc;
+    int ret;
+
+    sfc = devm_kzalloc(dev, sizeof(*sfc), GFP_KERNEL);
+    if (!sfc)
+        return -ENOMEM;
+
+    platform_set_drvdata(pdev, sfc);
+    sfc->dev = dev;
+
+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+    sfc->regbase = devm_ioremap_resource(dev, res);
+    if (IS_ERR(sfc->regbase))
+        return PTR_ERR(sfc->regbase);
+
+    sfc->clk = devm_clk_get(&pdev->dev, "sfc");
+    if (IS_ERR(sfc->clk)) {
+        dev_err(&pdev->dev, "Failed to get sfc interface clk\n");
+        return PTR_ERR(sfc->clk);
+    }
+
+    sfc->hclk = devm_clk_get(&pdev->dev, "hsfc");
+    if (IS_ERR(sfc->hclk)) {
+        dev_err(&pdev->dev, "Failed to get sfc ahp clk\n");
+        return PTR_ERR(sfc->hclk);
+    }
+
+    ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+    if (ret) {
+        dev_warn(dev, "Unable to set dma mask\n");
+        return ret;
+    }
+
+    sfc->buffer = dmam_alloc_coherent(dev, SFC_DMA_MAX_LEN,
+            &sfc->dma_buffer, GFP_KERNEL);
+    if (!sfc->buffer)
+        return -ENOMEM;
+
+    mutex_init(&sfc->lock);
+
+    ret = clk_prepare_enable(sfc->hclk);
+    if (ret) {
+        dev_err(&pdev->dev, "Failed to enable hclk\n");
+        goto err_hclk;
+    }
+
+    ret = clk_prepare_enable(sfc->clk);
+    if (ret) {
+        dev_err(&pdev->dev, "Failed to enable clk\n");
+        goto err_clk;
+    }
+
+    sfc->use_dma = !of_property_read_bool(sfc->dev->of_node,
+                          "rockchip,sfc-no-dma");
+
+    sfc->negative_edge = of_device_is_compatible(sfc->dev->of_node,
+                             "rockchip,rk1108-sfc");
I think this should rather be a boolean property -- but isn't this
something like CPOL or CPHA anyway ?
It isn't the same as CPOL or CPHA. And this value should be Soc
specificed.
So what is this about ? Can you explain what this negative_edge thing is
and how it works on the bus-level ?

[...]

-- 
Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help