Message ID | 20180212163858.25601-1-noltari@gmail.com |
---|---|
Headers | show |
Series | bmips: add bcm6348-enet support | expand |
No comments about DMA? 2018-02-12 17:38 GMT+01:00 Álvaro Fernández Rojas <noltari@gmail.com>: > In order to add bcm6348-enet support, dma-uclass must be extended to > support > dma channels and rewordked to operate like the other dm uclass (clk, > reset...). > > This is an RFC, so please give you feedback on the things that I should > fix or rework. > > Álvaro Fernández Rojas (14): > dma: add dma channels support and improve uclass > dma: add bcm6348-iudma support > bmips: bcm6338: add bcm6348-iudma support > bmips: bcm6348: add bcm6348-iudma support > bmips: bcm6358: add bcm6348-iudma support > phy: add support for internal phys > net: add support for bcm6348-enet > bmips: bcm6338: add support for bcm6348-enet > bmips: enable f@st1704 enet support > bmips: bcm6348: add support for bcm6348-enet > bmips: enable ct-5361 enet support > bmips: bcm6358: add support for bcm6348-enet > bmips: enable hg556a enet support > bmips: enable nb4-ser enet support > > arch/mips/dts/brcm,bcm6338.dtsi | 29 ++ > arch/mips/dts/brcm,bcm6348.dtsi | 42 +++ > arch/mips/dts/brcm,bcm6358.dtsi | 46 +++ > arch/mips/dts/comtrend,ct-5361.dts | 12 + > arch/mips/dts/huawei,hg556a.dts | 12 + > arch/mips/dts/sagem,f@st1704.dts | 12 + > arch/mips/dts/sfr,nb4-ser.dts | 24 ++ > configs/comtrend_ct5361_ram_defconfig | 8 +- > configs/huawei_hg556a_ram_defconfig | 8 +- > configs/sagem_f@st1704_ram_defconfig | 9 +- > configs/sfr_nb4-ser_ram_defconfig | 8 +- > drivers/dma/Kconfig | 8 + > drivers/dma/Makefile | 1 + > drivers/dma/bcm6348-iudma.c | 498 ++++++++++++++++++++++++++++++ > ++ > drivers/dma/dma-uclass.c | 212 +++++++++++--- > drivers/mtd/spi/sf-uclass.c | 17 ++ > drivers/mtd/spi/spi_flash.c | 11 +- > drivers/net/Kconfig | 9 + > drivers/net/Makefile | 1 + > drivers/net/bcm6348-eth.c | 517 ++++++++++++++++++++++++++++++ > ++++ > include/configs/bmips_common.h | 5 +- > include/dma-uclass.h | 110 ++++++++ > include/dma.h | 226 +++++++++++---- > include/dt-bindings/dma/bcm6338-dma.h | 15 + > include/dt-bindings/dma/bcm6348-dma.h | 17 ++ > include/dt-bindings/dma/bcm6358-dma.h | 17 ++ > include/phy.h | 2 + > include/spi_flash.h | 3 + > 28 files changed, 1780 insertions(+), 99 deletions(-) > create mode 100644 drivers/dma/bcm6348-iudma.c > create mode 100644 drivers/net/bcm6348-eth.c > create mode 100644 include/dma-uclass.h > create mode 100644 include/dt-bindings/dma/bcm6338-dma.h > create mode 100644 include/dt-bindings/dma/bcm6348-dma.h > create mode 100644 include/dt-bindings/dma/bcm6358-dma.h > > -- > 2.11.0 > >
Hi Simon, El 20/02/2018 a las 19:49, Simon Glass escribió: > Hi Alvaro, > > On 20 February 2018 at 10:46, Álvaro Fernández Rojas <noltari@gmail.com> wrote: >> Move dma_ops to a separate header file, following other uclass implementations. >> >> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> >> --- >> drivers/dma/dma-uclass.c | 3 ++- >> include/dma-uclass.h | 38 ++++++++++++++++++++++++++++++++++++++ >> include/dma.h | 22 ---------------------- >> 3 files changed, 40 insertions(+), 23 deletions(-) >> create mode 100644 include/dma-uclass.h >> >> diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c >> index 3d0ce22fbc..6fd4e1b35d 100644 >> --- a/drivers/dma/dma-uclass.c >> +++ b/drivers/dma/dma-uclass.c >> @@ -10,10 +10,11 @@ >> */ >> >> #include <common.h> >> -#include <dma.h> >> #include <dm.h> >> #include <dm/uclass-internal.h> >> #include <dm/device-internal.h> >> +#include <dma.h> >> +#include <dma-uclass.h> >> #include <errno.h> >> >> DECLARE_GLOBAL_DATA_PTR; >> diff --git a/include/dma-uclass.h b/include/dma-uclass.h >> new file mode 100644 >> index 0000000000..e29ad103f2 >> --- /dev/null >> +++ b/include/dma-uclass.h >> @@ -0,0 +1,38 @@ >> +/* >> + * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com> >> + * Copyright (C) 2015 Texas Instruments Incorporated, <www.ti.com> >> + * Written by Mugunthan V N <mugunthanvnm@ti.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> + >> +#ifndef _DMA_UCLASS_H >> +#define _DMA_UCLASS_H >> + >> +/* See dma.h for background documentation. */ >> + >> +#include <dma.h> >> + >> +/* >> + * struct dma_ops - Driver model DMA operations >> + * >> + * The uclass interface is implemented by all DMA devices which use >> + * driver model. >> + */ >> +struct dma_ops { >> + /* >> + * Get the current timer count > Is this the correct purpose for the transfer() method? This is just a copy&paste, that's what you can find in upstream dma.h ;D Anyway, I will fix that. >> + * >> + * @dev: The DMA device >> + * @direction: direction of data transfer should be one from >> + enum dma_direction >> + * @dst: Destination pointer >> + * @src: Source pointer >> + * @len: Length of the data to be copied. > Is this the number of bytes > > What does this function actually do? Does it queue a transfer which > completes later? How do I check if it is done? > > Please add a lot more docs here. Same as above. > >> + * @return: 0 if OK, -ve on error >> + */ >> + int (*transfer)(struct udevice *dev, int direction, void *dst, >> + void *src, size_t len); >> +}; >> + >> +#endif /* _DMA_UCLASS_H */ >> diff --git a/include/dma.h b/include/dma.h >> index 71fa77f2ea..89320f10d9 100644 >> --- a/include/dma.h >> +++ b/include/dma.h >> @@ -28,28 +28,6 @@ enum dma_direction { >> #define DMA_SUPPORTS_DEV_TO_DEV BIT(3) >> >> /* >> - * struct dma_ops - Driver model DMA operations >> - * >> - * The uclass interface is implemented by all DMA devices which use >> - * driver model. >> - */ >> -struct dma_ops { >> - /* >> - * Get the current timer count >> - * >> - * @dev: The DMA device >> - * @direction: direction of data transfer should be one from >> - enum dma_direction >> - * @dst: Destination pointer >> - * @src: Source pointer >> - * @len: Length of the data to be copied. >> - * @return: 0 if OK, -ve on error >> - */ >> - int (*transfer)(struct udevice *dev, int direction, void *dst, >> - void *src, size_t len); >> -}; >> - >> -/* >> * struct dma_dev_priv - information about a device used by the uclass >> * >> * @supported: mode of transfers that DMA can support, should be >> -- >> 2.11.0 >> > Regards, > Simon Regards, Álvaro.
Hi Simon, El 20/02/2018 a las 19:49, Simon Glass escribió: > Hi Alvaro, > > On 20 February 2018 at 10:46, Álvaro Fernández Rojas <noltari@gmail.com> wrote: >> This adds channels support for dma controllers that have multiple channels >> which can transfer data to/from different devices (enet, usb...). >> >> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> >> --- >> v2: Introduce changes reported by Vignesh: >> - Respect current dma implementation. >> - Let dma_memcpy find a compatible dma device. >> >> drivers/dma/Kconfig | 7 ++ >> drivers/dma/dma-uclass.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++ >> include/dma-uclass.h | 77 +++++++++++++++++++++ >> include/dma.h | 169 ++++++++++++++++++++++++++++++++++++++++++++ >> 4 files changed, 430 insertions(+) >> >> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig >> index 1b92c7789d..21b2c0dcaa 100644 >> --- a/drivers/dma/Kconfig >> +++ b/drivers/dma/Kconfig >> @@ -12,6 +12,13 @@ config DMA >> buses that is used to transfer data to and from memory. >> The uclass interface is defined in include/dma.h. >> >> +config DMA_CHANNELS >> + bool "Enable DMA channels support" >> + depends on DMA >> + help >> + Enable channels support for DMA. Some DMA controllers have multiple >> + channels which can either transfer data to/from different devices. >> + >> config TI_EDMA3 >> bool "TI EDMA3 driver" >> help >> diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c >> index 6fd4e1b35d..a16c3a786c 100644 >> --- a/drivers/dma/dma-uclass.c >> +++ b/drivers/dma/dma-uclass.c >> @@ -15,10 +15,187 @@ >> #include <dm/device-internal.h> >> #include <dma.h> >> #include <dma-uclass.h> >> +#include <dt-structs.h> >> #include <errno.h> >> >> DECLARE_GLOBAL_DATA_PTR; >> >> +#ifdef CONFIG_DMA_CHANNELS >> +static inline struct dma_ops *dma_dev_ops(struct udevice *dev) >> +{ >> + return (struct dma_ops *)dev->driver->ops; >> +} >> + >> +# if CONFIG_IS_ENABLED(OF_CONTROL) >> +# if CONFIG_IS_ENABLED(OF_PLATDATA) >> +int dma_get_by_index_platdata(struct udevice *dev, int index, >> + struct phandle_2_cell *cells, struct dma *dma) >> +{ >> + int ret; >> + >> + if (index != 0) >> + return -ENOSYS; >> + ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev); >> + if (ret) >> + return ret; >> + dma->id = cells[0].id; >> + >> + return 0; >> +} >> +# else >> +static int dma_of_xlate_default(struct dma *dma, >> + struct fdtdec_phandle_args *args) >> +{ >> + debug("%s(dma=%p)\n", __func__, dma); >> + >> + if (args->args_count > 1) { >> + pr_err("Invaild args_count: %d\n", args->args_count); >> + return -EINVAL; >> + } >> + >> + if (args->args_count) >> + dma->id = args->args[0]; >> + else >> + dma->id = 0; >> + >> + return 0; >> +} >> + >> +int dma_get_by_index(struct udevice *dev, int index, struct dma *dma) >> +{ >> + int ret; >> + struct fdtdec_phandle_args args; >> + struct udevice *dev_dma; >> + struct dma_ops *ops; >> + >> + debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma); >> + >> + assert(dma); >> + ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), >> + "dmas", "#dma-cells", 0, index, >> + &args); > Can you please use the livetree API? E.g. see dev_read_phandle_with_args() > > Also please move this into an ofdata_to_platdata function rather than > doing it each time this function is called. Ok, I did this some time ago and I used an older version of clk-uclass as a starting point. I will switch to livetree in the next patch version. > >> + if (ret) { >> + pr_err("%s: fdtdec_parse_phandle_with_args failed: err=%d\n", >> + __func__, ret); >> + return ret; >> + } >> + >> + ret = uclass_get_device_by_of_offset(UCLASS_DMA, args.node, &dev_dma); >> + if (ret) { >> + pr_err("%s: uclass_get_device_by_of_offset failed: err=%d\n", >> + __func__, ret); >> + return ret; >> + } >> + >> + dma->dev = dev_dma; >> + >> + ops = dma_dev_ops(dev_dma); >> + >> + if (ops->of_xlate) >> + ret = ops->of_xlate(dma, &args); >> + else >> + ret = dma_of_xlate_default(dma, &args); >> + if (ret) { >> + pr_err("of_xlate() failed: %d\n", ret); >> + return ret; >> + } >> + >> + return dma_request(dev_dma, dma); >> +} >> +# endif /* OF_PLATDATA */ >> + >> +int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma) >> +{ >> + int index; >> + >> + debug("%s(dev=%p, name=%s, dma=%p)\n", __func__, dev, name, dma); >> + >> + index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), >> + "dma-names", name); > dev_read... Ok. > >> + if (index < 0) { >> + pr_err("fdt_stringlist_search() failed: %d\n", index); >> + return index; >> + } >> + >> + return dma_get_by_index(dev, index, dma); >> +} >> +# endif /* OF_CONTROL */ >> + >> +int dma_request(struct udevice *dev, struct dma *dma) >> +{ >> + struct dma_ops *ops = dma_dev_ops(dev); >> + >> + debug("%s(dev=%p, dma=%p)\n", __func__, dev, dma); >> + >> + dma->dev = dev; >> + >> + if (!ops->request) >> + return 0; >> + >> + return ops->request(dma); >> +} >> + >> +int dma_free(struct dma *dma) >> +{ >> + struct dma_ops *ops = dma_dev_ops(dma->dev); >> + >> + debug("%s(dma=%p)\n", __func__, dma); >> + >> + if (!ops->free) >> + return 0; >> + >> + return ops->free(dma); >> +} >> + >> +int dma_enable(struct dma *dma) >> +{ >> + struct dma_ops *ops = dma_dev_ops(dma->dev); >> + >> + debug("%s(dma=%p)\n", __func__, dma); >> + >> + if (!ops->enable) >> + return -ENOSYS; >> + >> + return ops->enable(dma); >> +} >> + >> +int dma_disable(struct dma *dma) >> +{ >> + struct dma_ops *ops = dma_dev_ops(dma->dev); >> + >> + debug("%s(dma=%p)\n", __func__, dma); >> + >> + if (!ops->disable) >> + return -ENOSYS; >> + >> + return ops->disable(dma); >> +} >> + >> +int dma_receive(struct dma *dma, void **dst) >> +{ >> + struct dma_ops *ops = dma_dev_ops(dma->dev); >> + >> + debug("%s(dma=%p)\n", __func__, dma); >> + >> + if (!ops->receive) >> + return -1; >> + >> + return ops->receive(dma, dst); >> +} >> + >> +int dma_send(struct dma *dma, void *src, size_t len) >> +{ >> + struct dma_ops *ops = dma_dev_ops(dma->dev); >> + >> + debug("%s(dma=%p)\n", __func__, dma); >> + >> + if (!ops->send) >> + return -1; >> + >> + return ops->send(dma, src, len); >> +} >> +#endif /* CONFIG_DMA_CHANNELS */ >> + >> int dma_get_device(u32 transfer_type, struct udevice **devp) >> { >> struct udevice *dev; >> diff --git a/include/dma-uclass.h b/include/dma-uclass.h >> index e29ad103f2..5faec69207 100644 >> --- a/include/dma-uclass.h >> +++ b/include/dma-uclass.h >> @@ -12,6 +12,7 @@ >> /* See dma.h for background documentation. */ >> >> #include <dma.h> >> +#include <fdtdec.h> >> >> /* >> * struct dma_ops - Driver model DMA operations >> @@ -20,6 +21,82 @@ >> * driver model. >> */ >> struct dma_ops { >> +#ifdef CONFIG_DMA_CHANNELS >> + /** >> + * of_xlate - Translate a client's device-tree (OF) DMA specifier. >> + * >> + * The DMA core calls this function as the first step in implementing >> + * a client's dma_get_by_*() call. >> + * >> + * If this function pointer is set to NULL, the DMA core will use a >> + * default implementation, which assumes #dma-cells = <1>, and that >> + * the DT cell contains a simple integer DMA Channel. >> + * >> + * At present, the DMA API solely supports device-tree. If this >> + * changes, other xxx_xlate() functions may be added to support those >> + * other mechanisms. >> + * >> + * @dma: The dma struct to hold the translation result. >> + * @args: The dma specifier values from device tree. >> + * @return 0 if OK, or a negative error code. >> + */ >> + int (*of_xlate)(struct dma *dma, >> + struct fdtdec_phandle_args *args); > Use new livetree struct here Ok. > > Regards, > Simon Regards, Álvaro.