* Re: [RFC,V2,1/2] media: dt-bindings: media: i2c: Add bindings for OV02A10
From: Dongchun Zhu @ 2019-08-17 3:53 UTC (permalink / raw)
To: sakari.ailus
Cc: mark.rutland, devicetree, drinkcat, srv_heupstream, menghui.lin,
tfiga, shengnan.wang, louis.kuo, sj.huang, robh+dt,
linux-mediatek, matthias.bgg, bingbu.cao, mchehab,
linux-arm-kernel, linux-media
In-Reply-To: <ef65288c523f405396991bd6d757bba0@mtkmbs02n1.mediatek.inc>
Hi Sakari,
On Tue, 2019-07-23 at 10:41 +0300, Sakari Ailus wrote:
>
> Hi Dongchun,
>
> On Thu, Jul 04, 2019 at 04:46:50PM +0800, dongchun.zhu@mediatek.com wrote:
> > From: Dongchun Zhu <dongchun.zhu@mediatek.com>
> >
> > Add device tree binding documentation for the OV02A10 camera sensor.
> >
> > Signed-off-by: Dongchun Zhu <dongchun.zhu@mediatek.com>
> > ---
> > .../devicetree/bindings/media/i2c/ov02a10.txt | 43 ++++++++++++++++++++++
> > MAINTAINERS | 7 ++++
> > 2 files changed, 50 insertions(+)
> > create mode 100644
> > Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> >
> > diff --git a/Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> > b/Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> > new file mode 100644
> > index 0000000..d40aa87
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> > @@ -0,0 +1,43 @@
> > +* Omnivision OV02A10 MIPI CSI-2 sensor
> > +
> > +Required Properties:
> > +- compatible: shall be "ovti,ov02a10"
> > +- clocks: reference to the xvclk input clock
> > +- clock-names: shall be "xvclk"
> > +- avdd-supply: Analog voltage supply, 2.8 volts
> > +- dovdd-supply: Digital I/O voltage supply, 1.8 volts
> > +- dvdd-supply: Digital core voltage supply, 1.8 volts
> > +- reset-gpios: Low active reset gpio
> > +
> > +The device node shall contain one 'port' child node with an
> > +'endpoint' subnode for its digital output video port, in accordance
> > +with the video interface bindings defined in
> > +Documentation/devicetree/bindings/media/video-interfaces.txt.
> > +The endpoint optional property 'data-lanes' shall be "<1>".
>
> How many lanes does the module (or the sensor) have?
>
From sensor datasheet, OV02A10 supports 1-lane MIPI interface.
> > +
> > +Example:
> > +&i2c4 {
> > +ov02a10: camera-sensor@3d {
> > +compatible = "ovti,ov02a10";
> > +reg = <0x3d>;
> > +pinctrl-names = "default";
> > +pinctrl-0 = <&camera_pins_cam1_mclk_on>;
> > +
> > +clocks = <&topckgen CLK_TOP_MUX_CAMTG2>,
> > +<&topckgen CLK_TOP_UNIVP_192M_D8>;
> > +clock-names = "xvclk", "freq_mux";
> > +
> > +avdd-supply = <&mt6358_vcama1_reg>;
> > +dvdd-supply = <&mt6358_vcn18_reg>;
> > +dovdd-supply = <&mt6358_vcamio_reg>;
> > +pwdn-gpios = <&pio 107 1>;
> > +reset-gpios = <&pio 109 1>;
> > +
> > +port {
> > + ov02a10_core: endpoint {
> > + remote-endpoint = <&ov02a10_0>;
>
> Indentation is still wrong. :-(
>
Fixed in next release.
> > + data-lanes = <1>;
> > +};
> > +};
> > +};
> > +};
> > diff --git a/MAINTAINERS b/MAINTAINERS index 5cfbea4..62b81ff 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -11571,6 +11571,13 @@ T:git git://linuxtv.org/media_tree.git
> > S:Maintained
> > F:drivers/media/i2c/ov13858.c
> >
> > +OMNIVISION OV02A10 SENSOR DRIVER
> > +M:Dongchun Zhu <dongchun.zhu@mediatek.com>
> > +L:linux-media@vger.kernel.org
> > +T:git git://linuxtv.org/media_tree.git
> > +S:Maintained
> > +F:Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> > +
> > OMNIVISION OV2680 SENSOR DRIVER
> > M:Rui Miguel Silva <rmfrfs@gmail.com>
> > L:linux-media@vger.kernel.org
>
> --
> Kind regards,
>
> Sakari Ailus
> sakari.ailus@linux.intel.com
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
> *********************MEDIATEK Confidential/Internal Use*********************
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 4/5] clk: Add driver for Bitmain BM1880 SoC clock controller
From: Manivannan Sadhasivam @ 2019-08-17 3:55 UTC (permalink / raw)
To: Stephen Boyd
Cc: devicetree, mturquette, linux-kernel, darren.tsao, robh+dt,
haitao.suo, fisher.cheng, alec.lin, linux-clk, linux-arm-kernel
In-Reply-To: <20190808051600.4EF7D2186A@mail.kernel.org>
Hi Stephen,
On Wed, Aug 07, 2019 at 10:15:59PM -0700, Stephen Boyd wrote:
> Quoting Manivannan Sadhasivam (2019-07-05 08:14:39)
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> > index fc1e0cf44995..ffc61ed85ade 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -304,6 +304,12 @@ config COMMON_CLK_FIXED_MMIO
> > help
> > Support for Memory Mapped IO Fixed clocks
> >
> > +config COMMON_CLK_BM1880
> > + bool "Clock driver for Bitmain BM1880 SoC"
> > + depends on ARCH_BITMAIN || COMPILE_TEST
> > + help
> > + This driver supports the clocks on Bitmain BM1880 SoC.
>
> Can you add this config somewhere else besides the end? Preferably
> close to alphabetically in this file.
>
Okay. I got confused by the fact that Makefile is sorted but not the
Kconfig.
> > +
> > source "drivers/clk/actions/Kconfig"
> > source "drivers/clk/analogbits/Kconfig"
> > source "drivers/clk/bcm/Kconfig"
> > diff --git a/drivers/clk/clk-bm1880.c b/drivers/clk/clk-bm1880.c
> > new file mode 100644
> > index 000000000000..26cdb75bb936
> > --- /dev/null
> > +++ b/drivers/clk/clk-bm1880.c
> > @@ -0,0 +1,947 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Bitmain BM1880 SoC clock driver
> > + *
> > + * Copyright (c) 2019 Linaro Ltd.
> > + * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/of_address.h>
> > +#include <linux/slab.h>
>
> Should probably add kernel.h for at least container_of()
>
okay.
> > +
> > +#include <dt-bindings/clock/bm1880-clock.h>
> > +
> > +#define BM1880_CLK_MPLL_CTL 0x00
> > +#define BM1880_CLK_SPLL_CTL 0x04
> > +#define BM1880_CLK_FPLL_CTL 0x08
> > +#define BM1880_CLK_DDRPLL_CTL 0x0c
> > +
> > +#define BM1880_CLK_ENABLE0 0x00
> > +#define BM1880_CLK_ENABLE1 0x04
> > +#define BM1880_CLK_SELECT 0x20
> > +#define BM1880_CLK_DIV0 0x40
> > +#define BM1880_CLK_DIV1 0x44
> > +#define BM1880_CLK_DIV2 0x48
> > +#define BM1880_CLK_DIV3 0x4c
> > +#define BM1880_CLK_DIV4 0x50
> > +#define BM1880_CLK_DIV5 0x54
> > +#define BM1880_CLK_DIV6 0x58
> > +#define BM1880_CLK_DIV7 0x5c
> > +#define BM1880_CLK_DIV8 0x60
> > +#define BM1880_CLK_DIV9 0x64
> > +#define BM1880_CLK_DIV10 0x68
> > +#define BM1880_CLK_DIV11 0x6c
> > +#define BM1880_CLK_DIV12 0x70
> > +#define BM1880_CLK_DIV13 0x74
> > +#define BM1880_CLK_DIV14 0x78
> > +#define BM1880_CLK_DIV15 0x7c
> > +#define BM1880_CLK_DIV16 0x80
> > +#define BM1880_CLK_DIV17 0x84
> > +#define BM1880_CLK_DIV18 0x88
> > +#define BM1880_CLK_DIV19 0x8c
> > +#define BM1880_CLK_DIV20 0x90
> > +#define BM1880_CLK_DIV21 0x94
> > +#define BM1880_CLK_DIV22 0x98
> > +#define BM1880_CLK_DIV23 0x9c
> > +#define BM1880_CLK_DIV24 0xa0
> > +#define BM1880_CLK_DIV25 0xa4
> > +#define BM1880_CLK_DIV26 0xa8
> > +#define BM1880_CLK_DIV27 0xac
> > +#define BM1880_CLK_DIV28 0xb0
> > +
> > +#define to_bm1880_pll_clk(_hw) container_of(_hw, struct bm1880_pll_hw_clock, hw)
> > +#define to_bm1880_div_clk(_hw) container_of(_hw, struct bm1880_div_hw_clock, hw)
> > +
> > +static DEFINE_SPINLOCK(bm1880_clk_lock);
> > +
> > +struct bm1880_clock_data {
> > + void __iomem *pll_base;
> > + void __iomem *sys_base;
> > + struct clk_onecell_data clk_data;
> > +};
> > +
> > +struct bm1880_gate_clock {
> > + unsigned int id;
> > + const char *name;
> > + const char *parent;
> > + u32 gate_reg;
> > + s8 gate_shift;
> > + unsigned long flags;
> > +};
> > +
> > +struct bm1880_mux_clock {
> > + unsigned int id;
> > + const char *name;
> > + const char * const * parents;
> > + s8 num_parents;
> > + u32 reg;
> > + s8 shift;
> > + unsigned long flags;
> > +};
> > +
> > +struct bm1880_div_clock {
> > + unsigned int id;
> > + const char *name;
> > + const char *parent;
> > + u32 reg;
> > + u8 shift;
> > + u8 width;
> > + u32 initval;
> > + struct clk_div_table *table;
> > + unsigned long flags;
> > +};
> > +
> > +struct bm1880_div_hw_clock {
> > + struct bm1880_div_clock div;
> > + void __iomem *base;
> > + spinlock_t *lock;
> > + struct clk_hw hw;
> > +};
> > +
> > +struct bm1880_composite_clock {
> > + unsigned int id;
> > + const char *name;
> > + const char *parent;
> > + const char * const * parents;
> > + unsigned int num_parents;
> > + unsigned long flags;
> > +
> > + u32 gate_reg;
> > + u32 mux_reg;
> > + u32 div_reg;
> > +
> > + s8 gate_shift;
> > + s8 mux_shift;
> > + s8 div_shift;
> > + s8 div_width;
> > + s16 div_initval;
> > + struct clk_div_table *table;
> > +};
> > +
> > +struct bm1880_pll_clock {
> > + unsigned int id;
> > + const char *name;
> > + const char *parent;
> > + u32 reg;
> > + unsigned long flags;
> > +};
> > +
> > +struct bm1880_pll_hw_clock {
> > + struct bm1880_pll_clock pll;
> > + void __iomem *base;
> > + struct clk_hw hw;
> > +};
> > +
> > +#define GATE_DIV(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \
> > + _div_shift, _div_width, _div_initval, _table, \
> > + _flags) { \
> > + .id = _id, \
> > + .parent = _parent, \
> > + .name = _name, \
> > + .gate_reg = _gate_reg, \
> > + .gate_shift = _gate_shift, \
> > + .div_reg = _div_reg, \
> > + .div_shift = _div_shift, \
> > + .div_width = _div_width, \
> > + .div_initval = _div_initval, \
> > + .table = _table, \
> > + .mux_shift = -1, \
> > + .flags = _flags, \
> > + }
> > +
> > +#define GATE_MUX(_id, _name, _parents, _gate_reg, _gate_shift, \
> > + _mux_reg, _mux_shift, _flags) { \
> > + .id = _id, \
> > + .parents = _parents, \
> > + .num_parents = ARRAY_SIZE(_parents), \
> > + .name = _name, \
> > + .gate_reg = _gate_reg, \
> > + .gate_shift = _gate_shift, \
> > + .div_shift = -1, \
> > + .mux_reg = _mux_reg, \
> > + .mux_shift = _mux_shift, \
> > + .flags = _flags, \
> > + }
> > +
> > +static const struct bm1880_pll_clock bm1880_pll_clks[] = {
> > + { BM1880_CLK_MPLL, "clk_mpll", "osc", BM1880_CLK_MPLL_CTL,
> > + CLK_IS_CRITICAL },
> > + { BM1880_CLK_SPLL, "clk_spll", "osc", BM1880_CLK_SPLL_CTL,
> > + CLK_IS_CRITICAL },
> > + { BM1880_CLK_FPLL, "clk_fpll", "osc", BM1880_CLK_FPLL_CTL,
> > + CLK_IS_CRITICAL },
> > + { BM1880_CLK_DDRPLL, "clk_ddrpll", "osc", BM1880_CLK_DDRPLL_CTL,
> > + CLK_IS_CRITICAL },
> > +};
> > +
> > +static const struct bm1880_gate_clock bm1880_gate_clks[] = {
> > + { BM1880_CLK_AHB_ROM, "clk_ahb_rom", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE0, 2, CLK_IS_CRITICAL },
> > + { BM1880_CLK_AXI_SRAM, "clk_axi_sram", "clk_axi1",
> > + BM1880_CLK_ENABLE0, 3, CLK_IS_CRITICAL },
> > + { BM1880_CLK_DDR_AXI, "clk_ddr_axi", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE0, 4, CLK_IS_CRITICAL },
> > + { BM1880_CLK_APB_EFUSE, "clk_apb_efuse", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE0, 6, CLK_IS_CRITICAL },
> > + { BM1880_CLK_AXI5_EMMC, "clk_axi5_emmc", "clk_axi5",
> > + BM1880_CLK_ENABLE0, 7, 0 },
> > + { BM1880_CLK_AXI5_SD, "clk_axi5_sd", "clk_axi5",
> > + BM1880_CLK_ENABLE0, 10, 0 },
> > + { BM1880_CLK_AXI4_ETH0, "clk_axi4_eth0", "clk_axi4",
> > + BM1880_CLK_ENABLE0, 14, 0 },
> > + { BM1880_CLK_AXI4_ETH1, "clk_axi4_eth1", "clk_axi4",
> > + BM1880_CLK_ENABLE0, 16, 0 },
> > + { BM1880_CLK_AXI1_GDMA, "clk_axi1_gdma", "clk_axi1",
> > + BM1880_CLK_ENABLE0, 17, 0 },
> > + /* Don't gate GPIO clocks as it is not owned by the GPIO driver */
> > + { BM1880_CLK_APB_GPIO, "clk_apb_gpio", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE0, 18, CLK_IGNORE_UNUSED },
> > + { BM1880_CLK_APB_GPIO_INTR, "clk_apb_gpio_intr", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE0, 19, CLK_IGNORE_UNUSED },
> > + { BM1880_CLK_AXI1_MINER, "clk_axi1_miner", "clk_axi1",
> > + BM1880_CLK_ENABLE0, 21, 0 },
> > + { BM1880_CLK_AHB_SF, "clk_ahb_sf", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE0, 22, 0 },
> > + { BM1880_CLK_SDMA_AXI, "clk_sdma_axi", "clk_axi5",
> > + BM1880_CLK_ENABLE0, 23, 0 },
> > + { BM1880_CLK_APB_I2C, "clk_apb_i2c", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE0, 25, 0 },
> > + { BM1880_CLK_APB_WDT, "clk_apb_wdt", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE0, 26, 0 },
> > + { BM1880_CLK_APB_JPEG, "clk_apb_jpeg", "clk_axi6",
> > + BM1880_CLK_ENABLE0, 27, 0 },
> > + { BM1880_CLK_AXI5_NF, "clk_axi5_nf", "clk_axi5",
> > + BM1880_CLK_ENABLE0, 29, 0 },
> > + { BM1880_CLK_APB_NF, "clk_apb_nf", "clk_axi6",
> > + BM1880_CLK_ENABLE0, 30, 0 },
> > + { BM1880_CLK_APB_PWM, "clk_apb_pwm", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE1, 0, 0 },
> > + { BM1880_CLK_RV, "clk_rv", "clk_mux_rv",
> > + BM1880_CLK_ENABLE1, 1, 0 },
> > + { BM1880_CLK_APB_SPI, "clk_apb_spi", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE1, 2, 0 },
> > + { BM1880_CLK_UART_500M, "clk_uart_500m", "clk_div_uart_500m",
> > + BM1880_CLK_ENABLE1, 4, 0 },
> > + { BM1880_CLK_APB_UART, "clk_apb_uart", "clk_axi6",
> > + BM1880_CLK_ENABLE1, 5, 0 },
> > + { BM1880_CLK_APB_I2S, "clk_apb_i2s", "clk_axi6",
> > + BM1880_CLK_ENABLE1, 6, 0 },
> > + { BM1880_CLK_AXI4_USB, "clk_axi4_usb", "clk_axi4",
> > + BM1880_CLK_ENABLE1, 7, 0 },
> > + { BM1880_CLK_APB_USB, "clk_apb_usb", "clk_axi6",
> > + BM1880_CLK_ENABLE1, 8, 0 },
> > + { BM1880_CLK_12M_USB, "clk_12m_usb", "clk_div_12m_usb",
> > + BM1880_CLK_ENABLE1, 11, 0 },
> > + { BM1880_CLK_APB_VIDEO, "clk_apb_video", "clk_axi6",
> > + BM1880_CLK_ENABLE1, 12, 0 },
> > + { BM1880_CLK_APB_VPP, "clk_apb_vpp", "clk_axi6",
> > + BM1880_CLK_ENABLE1, 15, 0 },
> > + { BM1880_CLK_AXI6, "clk_axi6", "clk_mux_axi6",
> > + BM1880_CLK_ENABLE1, 21, CLK_IS_CRITICAL },
> > +};
> > +
> > +static const char * const clk_a53_parents[] = { "clk_spll", "clk_mpll" };
> > +static const char * const clk_rv_parents[] = { "clk_div_1_rv", "clk_div_0_rv" };
> > +static const char * const clk_axi1_parents[] = { "clk_div_1_axi1", "clk_div_0_axi1" };
> > +static const char * const clk_axi6_parents[] = { "clk_div_1_axi6", "clk_div_0_axi6" };
> > +
> > +static const struct bm1880_mux_clock bm1880_mux_clks[] = {
> > + { BM1880_CLK_MUX_RV, "clk_mux_rv", clk_rv_parents, 2,
> > + BM1880_CLK_SELECT, 1, 0 },
> > + { BM1880_CLK_MUX_AXI6, "clk_mux_axi6", clk_axi6_parents, 2,
> > + BM1880_CLK_SELECT, 3, 0 },
> > +};
> > +
> > +static struct clk_div_table bm1880_div_table_0[] = {
>
> Can these tables be const?
>
Ack.
> > + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
> > + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },
> > + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },
> > + { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },
> > + { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },
> > + { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },
> > + { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },
> > + { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },
> > + { 0, 0 }
> > +};
> > +
> > +static struct clk_div_table bm1880_div_table_1[] = {
> > + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
> > + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },
> > + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },
> > + { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },
> > + { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },
> > + { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },
> > + { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },
> > + { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },
> > + { 127, 128 }, { 0, 0 }
> > +};
> > +
> > +static struct clk_div_table bm1880_div_table_2[] = {
> > + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
> > + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },
> > + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },
> > + { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },
> > + { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },
> > + { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },
> > + { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },
> > + { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },
> > + { 127, 128 }, { 255, 256 }, { 0, 0 }
> > +};
> > +
> > +static struct clk_div_table bm1880_div_table_3[] = {
> > + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
> > + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },
> > + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },
> > + { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },
> > + { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },
> > + { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },
> > + { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },
> > + { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },
> > + { 127, 128 }, { 255, 256 }, { 511, 512 }, { 0, 0 }
> > +};
> > +
> > +static struct clk_div_table bm1880_div_table_4[] = {
> > + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
> > + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },
> > + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },
> > + { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },
> > + { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },
> > + { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },
> > + { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },
> > + { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },
> > + { 127, 128 }, { 255, 256 }, { 511, 512 }, { 65535, 65536 },
> > + { 0, 0 }
> > +};
> > +
> > +static const struct bm1880_div_clock bm1880_div_clks[] = {
> > + { BM1880_CLK_DIV_0_RV, "clk_div_0_rv", "clk_spll",
> > + BM1880_CLK_DIV12, 16, 5, 1, bm1880_div_table_0, CLK_IGNORE_UNUSED },
> > + { BM1880_CLK_DIV_1_RV, "clk_div_1_rv", "clk_fpll",
> > + BM1880_CLK_DIV13, 16, 5, 1, bm1880_div_table_0, CLK_IGNORE_UNUSED },
> > + { BM1880_CLK_DIV_UART_500M, "clk_div_uart_500m", "clk_fpll",
> > + BM1880_CLK_DIV15, 16, 7, 3, bm1880_div_table_1, 0 },
> > + { BM1880_CLK_DIV_0_AXI1, "clk_div_0_axi1", "clk_mpll",
> > + BM1880_CLK_DIV21, 16, 5, 2, bm1880_div_table_0, CLK_IS_CRITICAL },
> > + { BM1880_CLK_DIV_1_AXI1, "clk_div_1_axi1", "clk_fpll",
> > + BM1880_CLK_DIV22, 16, 5, 3, bm1880_div_table_0, CLK_IS_CRITICAL },
> > + { BM1880_CLK_DIV_0_AXI6, "clk_div_0_axi6", "clk_fpll",
> > + BM1880_CLK_DIV27, 16, 5, 15, bm1880_div_table_0, CLK_IS_CRITICAL },
> > + { BM1880_CLK_DIV_1_AXI6, "clk_div_1_axi6", "clk_mpll",
> > + BM1880_CLK_DIV28, 16, 5, 11, bm1880_div_table_0, CLK_IS_CRITICAL },
> > + { BM1880_CLK_DIV_12M_USB, "clk_div_12m_usb", "clk_fpll",
> > + BM1880_CLK_DIV18, 16, 7, 125, bm1880_div_table_1, 0 },
> > +};
> > +
> > +static struct bm1880_composite_clock bm1880_composite_clks[] = {
> > + GATE_MUX(BM1880_CLK_A53, "clk_a53", clk_a53_parents,
> > + BM1880_CLK_ENABLE0, 0, BM1880_CLK_SELECT, 0,
> > + CLK_IS_CRITICAL),
>
> Please document why CLK_IS_CRITICAL. Maybe CPU clk so must be kept on?
>
Yeah, will add comments for all critical clocks.
> > + GATE_DIV(BM1880_CLK_50M_A53, "clk_50m_a53", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 1, BM1880_CLK_DIV0, 16, 5, 30,
> > + bm1880_div_table_0, CLK_IS_CRITICAL),
> > + GATE_DIV(BM1880_CLK_EFUSE, "clk_efuse", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 5, BM1880_CLK_DIV1, 16, 7, 60,
> > + bm1880_div_table_1, 0),
> > + GATE_DIV(BM1880_CLK_EMMC, "clk_emmc", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 8, BM1880_CLK_DIV2, 16, 5, 15,
> > + bm1880_div_table_0, 0),
> > + GATE_DIV(BM1880_CLK_100K_EMMC, "clk_100k_emmc", "clk_div_12m_usb",
> > + BM1880_CLK_ENABLE0, 9, BM1880_CLK_DIV3, 16, 8, 120,
> > + bm1880_div_table_2, 0),
> > + GATE_DIV(BM1880_CLK_SD, "clk_sd", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 11, BM1880_CLK_DIV4, 16, 5, 15,
> > + bm1880_div_table_0, 0),
> > + GATE_DIV(BM1880_CLK_100K_SD, "clk_100k_sd", "clk_div_12m_usb",
> > + BM1880_CLK_ENABLE0, 12, BM1880_CLK_DIV5, 16, 8, 120,
> > + bm1880_div_table_2, 0),
> > + GATE_DIV(BM1880_CLK_500M_ETH0, "clk_500m_eth0", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 13, BM1880_CLK_DIV6, 16, 5, 3,
> > + bm1880_div_table_0, 0),
> > + GATE_DIV(BM1880_CLK_500M_ETH1, "clk_500m_eth1", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 15, BM1880_CLK_DIV7, 16, 5, 3,
> > + bm1880_div_table_0, 0),
> > + /* Don't gate GPIO clocks as it is not owned by the GPIO driver */
> > + GATE_DIV(BM1880_CLK_GPIO_DB, "clk_gpio_db", "clk_div_12m_usb",
> > + BM1880_CLK_ENABLE0, 20, BM1880_CLK_DIV8, 16, 16, 120,
> > + bm1880_div_table_4, CLK_IGNORE_UNUSED),
> > + GATE_DIV(BM1880_CLK_SDMA_AUD, "clk_sdma_aud", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 24, BM1880_CLK_DIV9, 16, 7, 61,
> > + bm1880_div_table_1, 0),
> > + GATE_DIV(BM1880_CLK_JPEG_AXI, "clk_jpeg_axi", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 28, BM1880_CLK_DIV10, 16, 5, 4,
> > + bm1880_div_table_0, 0),
> > + GATE_DIV(BM1880_CLK_NF, "clk_nf", "clk_fpll",
> > + BM1880_CLK_ENABLE0, 31, BM1880_CLK_DIV11, 16, 5, 30,
> > + bm1880_div_table_0, 0),
> > + GATE_DIV(BM1880_CLK_TPU_AXI, "clk_tpu_axi", "clk_spll",
> > + BM1880_CLK_ENABLE1, 3, BM1880_CLK_DIV14, 16, 5, 1,
> > + bm1880_div_table_0, 0),
> > + GATE_DIV(BM1880_CLK_125M_USB, "clk_125m_usb", "clk_fpll",
> > + BM1880_CLK_ENABLE1, 9, BM1880_CLK_DIV16, 16, 5, 12,
> > + bm1880_div_table_0, 0),
> > + GATE_DIV(BM1880_CLK_33K_USB, "clk_33k_usb", "clk_div_12m_usb",
> > + BM1880_CLK_ENABLE1, 10, BM1880_CLK_DIV17, 16, 9, 363,
> > + bm1880_div_table_3, 0),
> > + GATE_DIV(BM1880_CLK_VIDEO_AXI, "clk_video_axi", "clk_fpll",
> > + BM1880_CLK_ENABLE1, 13, BM1880_CLK_DIV19, 16, 5, 4,
> > + bm1880_div_table_0, 0),
> > + GATE_DIV(BM1880_CLK_VPP_AXI, "clk_vpp_axi", "clk_fpll",
> > + BM1880_CLK_ENABLE1, 14, BM1880_CLK_DIV20, 16, 5, 4,
> > + bm1880_div_table_0, 0),
> > + GATE_MUX(BM1880_CLK_AXI1, "clk_axi1", clk_axi1_parents,
> > + BM1880_CLK_ENABLE1, 15, BM1880_CLK_SELECT, 2,
> > + CLK_IS_CRITICAL),
> > + GATE_DIV(BM1880_CLK_AXI2, "clk_axi2", "clk_fpll",
> > + BM1880_CLK_ENABLE1, 17, BM1880_CLK_DIV23, 16, 5, 3,
> > + bm1880_div_table_0, CLK_IS_CRITICAL),
> > + GATE_DIV(BM1880_CLK_AXI3, "clk_axi3", "clk_mux_rv",
> > + BM1880_CLK_ENABLE1, 18, BM1880_CLK_DIV24, 16, 5, 2,
> > + bm1880_div_table_0, CLK_IS_CRITICAL),
> > + GATE_DIV(BM1880_CLK_AXI4, "clk_axi4", "clk_fpll",
> > + BM1880_CLK_ENABLE1, 19, BM1880_CLK_DIV25, 16, 5, 6,
> > + bm1880_div_table_0, CLK_IS_CRITICAL),
> > + GATE_DIV(BM1880_CLK_AXI5, "clk_axi5", "clk_fpll",
> > + BM1880_CLK_ENABLE1, 20, BM1880_CLK_DIV26, 16, 5, 15,
> > + bm1880_div_table_0, CLK_IS_CRITICAL),
> > +};
> > +
> > +static unsigned long bm1880_pll_rate_calc(u32 regval, unsigned long parent_rate)
> > +{
> > + u32 fbdiv, fref, refdiv;
> > + u32 postdiv1, postdiv2;
> > + unsigned long rate, numerator, denominator;
> > +
> > + fbdiv = (regval >> 16) & 0xfff;
> > + fref = parent_rate;
> > + refdiv = regval & 0x1f;
> > + postdiv1 = (regval >> 8) & 0x7;
> > + postdiv2 = (regval >> 12) & 0x7;
> > +
> > + numerator = parent_rate * fbdiv;
> > + denominator = refdiv * postdiv1 * postdiv2;
> > + do_div(numerator, denominator);
> > + rate = numerator;
> > +
> > + return rate;
> > +}
> > +
> > +static unsigned long bm1880_pll_recalc_rate(struct clk_hw *hw,
> > + unsigned long parent_rate)
> > +{
> > + struct bm1880_pll_hw_clock *pll_hw = to_bm1880_pll_clk(hw);
> > + unsigned long rate;
> > + u32 regval;
> > +
> > + regval = readl(pll_hw->base + pll_hw->pll.reg);
> > + rate = bm1880_pll_rate_calc(regval, parent_rate);
> > +
> > + return rate;
> > +}
> > +
> > +static const struct clk_ops bm1880_pll_ops = {
> > + .recalc_rate = bm1880_pll_recalc_rate,
> > +};
> > +
> > +struct clk *bm1880_clk_register_pll(const struct bm1880_pll_clock *pll_clk,
> > + void __iomem *sys_base)
> > +{
> > + struct bm1880_pll_hw_clock *pll_hw;
> > + struct clk_init_data init;
> > + struct clk_hw *hw;
> > + int err;
> > +
> > + pll_hw = kzalloc(sizeof(*pll_hw), GFP_KERNEL);
> > + if (!pll_hw)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + init.name = pll_clk->name;
> > + init.ops = &bm1880_pll_ops;
> > + init.flags = pll_clk->flags;
> > + init.parent_names = &pll_clk->parent;
>
> Can you use the new way of specifying parents instead of using strings
> for everything?
>
Sure, will do it for clocks which doesn't use helper APIs.
> > + init.num_parents = 1;
> > +
> > + pll_hw->hw.init = &init;
> > + pll_hw->pll.reg = pll_clk->reg;
> > + pll_hw->base = sys_base;
> > +
> > + hw = &pll_hw->hw;
> > + err = clk_hw_register(NULL, hw);
> > +
> > + if (err) {
> > + kfree(pll_hw);
> > + return ERR_PTR(err);
> > + }
> > +
> > + return hw->clk;
>
> Can this return the clk_hw pointer instead?
>
What is the benefit? I see that only hw:init is going to be NULL in future.
So, I'll keep it as it is.
> > +}
> > +
> > +void bm1880_clk_unregister_pll(struct clk *clk)
>
> Should this be static?
>
Ack.
> > +{
> > + struct bm1880_pll_hw_clock *pll_hw;
> > + struct clk_hw *hw;
> > +
> > + hw = __clk_get_hw(clk);
> > + if (!hw)
> > + return;
> > +
> > + pll_hw = to_bm1880_pll_clk(hw);
> > +
> > + clk_unregister(clk);
> > + kfree(pll_hw);
> > +}
> > +
> > +int bm1880_clk_register_plls(const struct bm1880_pll_clock *clks,
> > + int num_clks, struct bm1880_clock_data *data)
> > +{
> > + struct clk *clk;
> > + void __iomem *pll_base = data->pll_base;
> > + int i;
> > +
> > + for (i = 0; i < num_clks; i++) {
> > + const struct bm1880_pll_clock *bm1880_clk = &clks[i];
> > +
> > + clk = bm1880_clk_register_pll(bm1880_clk, pll_base);
> > + if (IS_ERR(clk)) {
> > + pr_err("%s: failed to register clock %s\n",
> > + __func__, bm1880_clk->name);
> > + goto err_clk;
> > + }
> > +
> > + data->clk_data.clks[clks[i].id] = clk;
> > + }
> > +
> > + return 0;
> > +
> > +err_clk:
> > + while (i--)
>
> I guess while (--i) is more idiomatic but this works too.
>
> > + bm1880_clk_unregister_pll(data->clk_data.clks[clks[i].id]);
> > +
> > + return PTR_ERR(clk);
> > +}
> > +
> > +int bm1880_clk_register_mux(const struct bm1880_mux_clock *clks,
> > + int num_clks, struct bm1880_clock_data *data)
> > +{
> > + struct clk *clk;
> > + void __iomem *sys_base = data->sys_base;
> > + int i;
> > +
> > + for (i = 0; i < num_clks; i++) {
> > + clk = clk_register_mux(NULL, clks[i].name,
>
> Can you use the clk_hw based APIs for generic type clks?
>
IMO using helper APIs greatly reduce code size and makes the driver
look more clean. So I prefer to use the helpers wherever applicable.
When you plan to deprecate those, I'll switch over to plain clk_hw APIs.
> > + clks[i].parents,
> > + clks[i].num_parents,
> > + clks[i].flags,
> > + sys_base + clks[i].reg,
> > + clks[i].shift, 1, 0,
> > + &bm1880_clk_lock);
> > + if (IS_ERR(clk)) {
> > + pr_err("%s: failed to register clock %s\n",
> > + __func__, clks[i].name);
> > + goto err_clk;
> > + }
> > +
> > + data->clk_data.clks[clks[i].id] = clk;
> > + }
> > +
> > + return 0;
> > +
> > +err_clk:
> > + while (i--)
> > + clk_unregister_gate(data->clk_data.clks[clks[i].id]);
> > +
> > + return PTR_ERR(clk);
> > +}
> > +
> > +static unsigned long bm1880_clk_div_recalc_rate(struct clk_hw *hw,
> > + unsigned long parent_rate)
> > +{
> > + struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);
> > + struct bm1880_div_clock *div = &div_hw->div;
> > + void __iomem *reg_addr = div_hw->base + div->reg;
> > + unsigned int val;
> > + unsigned long rate;
> > +
> > + if (!(readl(reg_addr) & BIT(3))) {
> > + val = div->initval;
> > + } else {
> > + val = readl(reg_addr) >> div->shift;
> > + val &= clk_div_mask(div->width);
> > + }
> > +
> > + rate = divider_recalc_rate(hw, parent_rate, val, div->table,
> > + div->flags, div->width);
> > +
> > + return rate;
> > +}
> > +
> > +static long bm1880_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
> > + unsigned long *prate)
> > +{
> > + struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);
> > + struct bm1880_div_clock *div = &div_hw->div;
> > + void __iomem *reg_addr = div_hw->base + div->reg;
> > +
> > + if (div->flags & CLK_DIVIDER_READ_ONLY) {
> > + u32 val;
> > +
> > + val = readl(reg_addr) >> div->shift;
> > + val &= clk_div_mask(div->width);
> > +
> > + return divider_ro_round_rate(hw, rate, prate, div->table,
> > + div->width, div->flags,
> > + val);
> > + }
> > +
> > + return divider_round_rate(hw, rate, prate, div->table,
> > + div->width, div->flags);
> > +}
> > +
> > +static int bm1880_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
> > + unsigned long parent_rate)
> > +{
> > + struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);
> > + struct bm1880_div_clock *div = &div_hw->div;
> > + void __iomem *reg_addr = div_hw->base + div->reg;
> > + unsigned long flags = 0;
> > + int value;
> > + u32 val;
> > +
> > + value = divider_get_val(rate, parent_rate, div->table,
> > + div->width, div_hw->div.flags);
> > + if (value < 0)
> > + return value;
> > +
> > + if (div_hw->lock)
> > + spin_lock_irqsave(div_hw->lock, flags);
> > + else
> > + __acquire(div_hw->lock);
> > +
> > + if (div->flags & CLK_DIVIDER_HIWORD_MASK) {
> > + val = clk_div_mask(div->width) << (div_hw->div.shift + 16);
> > + } else {
> > + val = readl(reg_addr);
> > + val &= ~(clk_div_mask(div->width) << div_hw->div.shift);
> > + }
> > + val |= (u32)value << div->shift;
> > + writel(val, reg_addr);
> > +
> > + if (div_hw->lock)
> > + spin_unlock_irqrestore(div_hw->lock, flags);
> > + else
> > + __release(div_hw->lock);
> > +
> > + return 0;
> > +}
> > +
> > +const struct clk_ops bm1880_clk_div_ops = {
>
> static?
>
Ack.
> > + .recalc_rate = bm1880_clk_div_recalc_rate,
> > + .round_rate = bm1880_clk_div_round_rate,
> > + .set_rate = bm1880_clk_div_set_rate,
> > +};
> > +
> > +struct clk *bm1880_clk_register_div(const struct bm1880_div_clock *div_clk,
> > + void __iomem *sys_base)
> > +{
> > + struct bm1880_div_hw_clock *div_hw;
> > + struct clk_init_data init;
> > + struct clk_hw *hw;
> > + int err;
> > +
> > + div_hw = kzalloc(sizeof(*div_hw), GFP_KERNEL);
> > + if (!div_hw)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + init.name = div_clk->name;
> > + init.ops = &bm1880_clk_div_ops;
> > + init.flags = div_clk->flags;
> > + init.parent_names = &div_clk->parent;
> > + init.num_parents = 1;
> > +
> > + div_hw->hw.init = &init;
> > + div_hw->div.reg = div_clk->reg;
> > + div_hw->div.shift = div_clk->shift;
> > + div_hw->div.width = div_clk->width;
> > + div_hw->div.initval = div_clk->initval;
> > + div_hw->div.table = div_clk->table;
> > + div_hw->div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
> > + div_hw->base = sys_base;
> > + div_hw->lock = &bm1880_clk_lock;
> > +
> > + hw = &div_hw->hw;
> > + err = clk_hw_register(NULL, hw);
> > +
> > + if (err) {
> > + kfree(div_hw);
> > + return ERR_PTR(err);
> > + }
> > +
> > + return hw->clk;
> > +}
> > +
> > +void bm1880_clk_unregister_div(struct clk *clk)
> > +{
> > + struct bm1880_div_hw_clock *div_hw;
> > + struct clk_hw *hw;
> > +
> > + hw = __clk_get_hw(clk);
> > + if (!hw)
> > + return;
> > +
> > + div_hw = to_bm1880_div_clk(hw);
> > +
> > + clk_unregister(clk);
> > + kfree(div_hw);
> > +}
> > +
> > +int bm1880_clk_register_divs(const struct bm1880_div_clock *clks,
> > + int num_clks, struct bm1880_clock_data *data)
> > +{
> > + struct clk *clk;
> > + void __iomem *sys_base = data->sys_base;
> > + int i;
> > +
> > + for (i = 0; i < num_clks; i++) {
> > + const struct bm1880_div_clock *bm1880_clk = &clks[i];
> > +
> > + clk = bm1880_clk_register_div(bm1880_clk, sys_base);
> > + if (IS_ERR(clk)) {
> > + pr_err("%s: failed to register clock %s\n",
> > + __func__, bm1880_clk->name);
> > + goto err_clk;
> > + }
> > +
> > + data->clk_data.clks[clks[i].id] = clk;
> > + }
> > +
> > + return 0;
> > +
> > +err_clk:
> > + while (i--)
> > + bm1880_clk_unregister_div(data->clk_data.clks[clks[i].id]);
> > +
> > + return PTR_ERR(clk);
> > +}
> > +
> > +int bm1880_clk_register_gate(const struct bm1880_gate_clock *clks,
> > + int num_clks, struct bm1880_clock_data *data)
> > +{
> > + struct clk *clk;
> > + void __iomem *sys_base = data->sys_base;
> > + int i;
> > +
> > + for (i = 0; i < num_clks; i++) {
> > + clk = clk_register_gate(NULL, clks[i].name,
> > + clks[i].parent,
> > + clks[i].flags,
> > + sys_base + clks[i].gate_reg,
> > + clks[i].gate_shift,
> > + 0,
> > + &bm1880_clk_lock);
> > + if (IS_ERR(clk)) {
> > + pr_err("%s: failed to register clock %s\n",
> > + __func__, clks[i].name);
> > + goto err_clk;
> > + }
> > +
> > + data->clk_data.clks[clks[i].id] = clk;
> > + }
> > +
> > + return 0;
> > +
> > +err_clk:
> > + while (i--)
> > + clk_unregister_gate(data->clk_data.clks[clks[i].id]);
> > +
> > + return PTR_ERR(clk);
> > +}
> > +
> > +struct clk *bm1880_clk_register_composite(struct bm1880_composite_clock *clks,
> > + void __iomem *sys_base)
> > +{
> > + struct clk *clk;
> > + struct clk_mux *mux = NULL;
> > + struct clk_gate *gate = NULL;
> > + struct bm1880_div_hw_clock *div_hws = NULL;
> > + struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
> > + const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
> > + const char * const *parent_names;
> > + const char *parent;
> > + int num_parents;
> > + int ret;
> > +
> > + if (clks->mux_shift >= 0) {
> > + mux = kzalloc(sizeof(*mux), GFP_KERNEL);
> > + if (!mux)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + mux->reg = sys_base + clks->mux_reg;
> > + mux->mask = 1;
> > + mux->shift = clks->mux_shift;
> > + mux_hw = &mux->hw;
> > + mux_ops = &clk_mux_ops;
> > + mux->lock = &bm1880_clk_lock;
> > +
> > + parent_names = clks->parents;
> > + num_parents = clks->num_parents;
> > + } else {
> > + parent = clks->parent;
> > + parent_names = &parent;
> > + num_parents = 1;
> > + }
> > +
> > + if (clks->gate_shift >= 0) {
> > + gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> > + if (!gate) {
> > + ret = -ENOMEM;
> > + goto err_out;
> > + }
> > +
> > + gate->reg = sys_base + clks->gate_reg;
> > + gate->bit_idx = clks->gate_shift;
> > + gate->lock = &bm1880_clk_lock;
> > +
> > + gate_hw = &gate->hw;
> > + gate_ops = &clk_gate_ops;
> > + }
> > +
> > + if (clks->div_shift >= 0) {
> > + div_hws = kzalloc(sizeof(*div_hws), GFP_KERNEL);
> > + if (!div_hws) {
> > + ret = -ENOMEM;
> > + goto err_out;
> > + }
> > +
> > + div_hws->base = sys_base;
> > + div_hws->div.reg = clks->div_reg;
> > + div_hws->div.shift = clks->div_shift;
> > + div_hws->div.width = clks->div_width;
> > + div_hws->div.table = clks->table;
> > + div_hws->div.initval = clks->div_initval;
> > + div_hws->lock = &bm1880_clk_lock;
> > + div_hws->div.flags = CLK_DIVIDER_ONE_BASED |
> > + CLK_DIVIDER_ALLOW_ZERO;
> > +
> > + div_hw = &div_hws->hw;
> > + div_ops = &bm1880_clk_div_ops;
> > + }
> > +
> > + clk = clk_register_composite(NULL, clks->name, parent_names,
> > + num_parents, mux_hw, mux_ops, div_hw,
> > + div_ops, gate_hw, gate_ops, (clks->flags));
> > +
> > + if (IS_ERR(clk)) {
> > + ret = PTR_ERR(clk);
> > + goto err_out;
> > + }
> > +
> > + return clk;
> > +
> > +err_out:
> > + kfree(div_hws);
> > + kfree(gate);
> > + kfree(mux);
> > +
> > + return ERR_PTR(ret);
> > +}
> > +
> > +int bm1880_clk_register_composites(struct bm1880_composite_clock *clks,
> > + int num_clks, struct bm1880_clock_data *data)
> > +{
> > + struct clk *clk;
> > + void __iomem *sys_base = data->sys_base;
> > + int i;
> > +
> > + for (i = 0; i < num_clks; i++) {
> > + struct bm1880_composite_clock *bm1880_clk = &clks[i];
> > +
> > + clk = bm1880_clk_register_composite(bm1880_clk, sys_base);
> > + if (IS_ERR(clk)) {
> > + pr_err("%s: failed to register clock %s\n",
> > + __func__, bm1880_clk->name);
> > + goto err_clk;
> > + }
> > +
> > + data->clk_data.clks[clks[i].id] = clk;
> > + }
> > +
> > + return 0;
> > +
> > +err_clk:
> > + while (i--)
> > + clk_unregister_composite(data->clk_data.clks[clks[i].id]);
> > +
> > + return PTR_ERR(clk);
> > +}
> > +
> > +static void bm1880_clk_init(struct device_node *np)
> > +{
> > + struct bm1880_clock_data *clk_data;
> > + struct clk **clk_table;
> > + void __iomem *pll_base, *sys_base;
> > + int num_clks;
> > +
> > + pll_base = of_iomap(np, 0);
> > + if (!pll_base) {
> > + pr_err("%pOFn: unable to map pll resource", np);
> > + of_node_put(np);
> > + return;
> > + }
> > +
> > + sys_base = of_iomap(np, 1);
> > + if (!sys_base) {
> > + pr_err("%pOFn: unable to map sys resource", np);
> > + of_node_put(np);
> > + return;
> > + }
> > +
> > + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> > + if (!clk_data)
> > + return;
> > +
> > + clk_data->pll_base = pll_base;
> > + clk_data->sys_base = sys_base;
> > + num_clks = ARRAY_SIZE(bm1880_gate_clks) +
> > + ARRAY_SIZE(bm1880_composite_clks);
> > +
> > + clk_table = kcalloc(num_clks, sizeof(*clk_table), GFP_KERNEL);
> > + if (!clk_table)
> > + goto err_out;
> > +
> > + clk_data->clk_data.clks = clk_table;
> > + clk_data->clk_data.clk_num = num_clks;
> > +
> > + /* Register PLL clocks */
> > + bm1880_clk_register_plls(bm1880_pll_clks,
> > + ARRAY_SIZE(bm1880_pll_clks),
> > + clk_data);
> > +
> > + /* Register Divider clocks */
>
> Please remove these comments, they provide no useful information.
>
Ack.
> > + bm1880_clk_register_divs(bm1880_div_clks,
> > + ARRAY_SIZE(bm1880_div_clks),
> > + clk_data);
> > +
> > + /* Register Mux clocks */
> > + bm1880_clk_register_mux(bm1880_mux_clks,
> > + ARRAY_SIZE(bm1880_mux_clks),
> > + clk_data);
> > +
> > + /* Register Composite clocks */
> > + bm1880_clk_register_composites(bm1880_composite_clks,
> > + ARRAY_SIZE(bm1880_composite_clks),
> > + clk_data);
> > +
> > + /* Register Gate clocks */
> > + bm1880_clk_register_gate(bm1880_gate_clks,
> > + ARRAY_SIZE(bm1880_gate_clks),
> > + clk_data);
> > +
> > + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
> > +
> > + return;
> > +
> > +err_out:
> > + kfree(clk_data);
> > +}
> > +
> > +CLK_OF_DECLARE_DRIVER(bm1880_clk, "bitmain,bm1880-clk", bm1880_clk_init);
>
> Is there a reason why it can't be a platform driver?
>
Hmm, I looked into the majority of drivers which live under `driver/clk/`.
Most of them are using CLK_OF_DECLARE_DRIVER, so I thought that only drivers
which have a separate directory are preferred by the maintainers to use
platform driver way.
Anyway, I can switch over to platform driver and that's what I prefer.
Thanks,
Mani
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/5] dt-bindings: clock: Add Bitmain BM1880 SoC clock controller binding
From: Manivannan Sadhasivam @ 2019-08-17 3:58 UTC (permalink / raw)
To: Stephen Boyd
Cc: devicetree, mturquette, linux-kernel, darren.tsao, robh+dt,
haitao.suo, fisher.cheng, alec.lin, linux-clk, linux-arm-kernel
In-Reply-To: <20190817034612.6DA7E21721@mail.kernel.org>
On Fri, Aug 16, 2019 at 08:46:11PM -0700, Stephen Boyd wrote:
> Quoting Manivannan Sadhasivam (2019-08-16 20:34:22)
> > On Wed, Aug 07, 2019 at 10:01:28PM -0700, Stephen Boyd wrote:
> > > Quoting Manivannan Sadhasivam (2019-07-05 08:14:36)
> > > > +It is expected that it is defined using standard clock bindings as "osc".
> > > > +
> > > > +Example:
> > > > +
> > > > + clk: clock-controller@800 {
> > > > + compatible = "bitmain,bm1880-clk";
> > > > + reg = <0xe8 0x0c>,<0x800 0xb0>;
> > >
> > > It looks weird still. What hardware module is this actually part of?
> > > Some larger power manager block?
> > >
> >
> > These are all part of the sysctrl block (clock + pinctrl + reset) and the
> > register domains got split between system and pll.
> >
>
> And that can't be one node that probes the clk, pinctrl, and reset
> drivers from C code?
It is not a MFD for sure. It's just grouping of the register domains together.
Thanks,
Mani
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC,V2,1/2] media: dt-bindings: media: i2c: Add bindings for OV02A10
From: Dongchun Zhu @ 2019-08-17 5:03 UTC (permalink / raw)
To: Rob Herring
Cc: mark.rutland, devicetree, drinkcat, srv_heupstream, menghui.lin,
Sakari Ailus, tfiga, shengnan.wang, louis.kuo, sj.huang, robh+dt,
linux-mediatek, matthias.bgg, bingbu.cao, mchehab,
linux-arm-kernel, linux-media
In-Reply-To: <5d5d644af9334609bb7c3ff745b2e754@mtkmbs02n1.mediatek.inc>
Hi Rob,
On Mon, 2019-07-22 at 18:49 -0500, Rob Herring wrote:
>
> On Thu, Jul 04, 2019 at 04:46:50PM +0800, dongchun.zhu@mediatek.com wrote:
> > From: Dongchun Zhu <dongchun.zhu@mediatek.com>
> >
> > Add device tree binding documentation for the OV02A10 camera sensor.
> >
> > Signed-off-by: Dongchun Zhu <dongchun.zhu@mediatek.com>
> > ---
> > .../devicetree/bindings/media/i2c/ov02a10.txt | 43 ++++++++++++++++++++++
> > MAINTAINERS | 7 ++++
> > 2 files changed, 50 insertions(+)
> > create mode 100644
> > Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> >
> > diff --git a/Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> > b/Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> > new file mode 100644
> > index 0000000..d40aa87
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> > @@ -0,0 +1,43 @@
> > +* Omnivision OV02A10 MIPI CSI-2 sensor
> > +
> > +Required Properties:
> > +- compatible: shall be "ovti,ov02a10"
> > +- clocks: reference to the xvclk input clock
> > +- clock-names: shall be "xvclk"
> > +- avdd-supply: Analog voltage supply, 2.8 volts
> > +- dovdd-supply: Digital I/O voltage supply, 1.8 volts
> > +- dvdd-supply: Digital core voltage supply, 1.8 volts
> > +- reset-gpios: Low active reset gpio
> > +
> > +The device node shall contain one 'port' child node with an
> > +'endpoint' subnode for its digital output video port, in accordance
> > +with the video interface bindings defined in
> > +Documentation/devicetree/bindings/media/video-interfaces.txt.
> > +The endpoint optional property 'data-lanes' shall be "<1>".
> > +
> > +Example:
> > +&i2c4 {
> > +ov02a10: camera-sensor@3d {
> > +compatible = "ovti,ov02a10";
> > +reg = <0x3d>;
> > +pinctrl-names = "default";
> > +pinctrl-0 = <&camera_pins_cam1_mclk_on>;
> > +
> > +clocks = <&topckgen CLK_TOP_MUX_CAMTG2>,
> > +<&topckgen CLK_TOP_UNIVP_192M_D8>;
> > +clock-names = "xvclk", "freq_mux";
> > +
> > +avdd-supply = <&mt6358_vcama1_reg>;
> > +dvdd-supply = <&mt6358_vcn18_reg>;
> > +dovdd-supply = <&mt6358_vcamio_reg>;
> > +pwdn-gpios = <&pio 107 1>;
>
> Not documented. If you need this, use 'powerdown-gpios' instead.
>
Fixed in next release.
> > +reset-gpios = <&pio 109 1>;
> > +
> > +port {
> > + ov02a10_core: endpoint {
> > + remote-endpoint = <&ov02a10_0>;
> > + data-lanes = <1>;
> > +};
> > +};
> > +};
> > +};
> > diff --git a/MAINTAINERS b/MAINTAINERS index 5cfbea4..62b81ff 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -11571,6 +11571,13 @@ T:git git://linuxtv.org/media_tree.git
> > S:Maintained
> > F:drivers/media/i2c/ov13858.c
> >
> > +OMNIVISION OV02A10 SENSOR DRIVER
> > +M:Dongchun Zhu <dongchun.zhu@mediatek.com>
> > +L:linux-media@vger.kernel.org
> > +T:git git://linuxtv.org/media_tree.git
> > +S:Maintained
> > +F:Documentation/devicetree/bindings/media/i2c/ov02a10.txt
> > +
> > OMNIVISION OV2680 SENSOR DRIVER
> > M:Rui Miguel Silva <rmfrfs@gmail.com>
> > L:linux-media@vger.kernel.org
> > --
> > 2.9.2
> >
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
> *********************MEDIATEK Confidential/Internal Use*********************
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC,V2,2/2] media: i2c: Add Omnivision OV02A10 camera sensor driver
From: Dongchun Zhu @ 2019-08-17 5:35 UTC (permalink / raw)
To: Bingbu Cao
Cc: mark.rutland, devicetree, drinkcat, srv_heupstream, tfiga,
shengnan.wang, louis.kuo, sj.huang, robh+dt, linux-mediatek,
matthias.bgg, bingbu.cao, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <8639e67ad6db40b78e48b00c875187dc@mtkmbs02n1.mediatek.inc>
Hi Bingbu,
On Tue, 2019-07-08 at 15:52 +0800, Bingbu Cao wrote:
> -----Original Message-----
> From: Linux-mediatek [mailto:linux-mediatek-bounces@lists.infradead.org] On Behalf Of Bingbu Cao
> Sent: Monday, July 08, 2019 3:53 PM
> To: Dongchun Zhu (朱东春) <Dongchun.Zhu@mediatek.com>; mchehab@kernel.org; robh+dt@kernel.org; mark.rutland@arm.com; sakari.ailus@linux.intel.com; --to=drinkcat@chromium.org; tfiga@chromium.org; matthias.bgg@gmail.com; bingbu.cao@intel.com
> Cc: devicetree@vger.kernel.org; srv_heupstream <srv_heupstream@mediatek.com>; Shengnan Wang (王圣男) <shengnan.wang@mediatek.com>; Sj Huang (黃信璋) <sj.huang@mediatek.com>; linux-mediatek@lists.infradead.org; Louis Kuo (郭德寧) <louis.kuo@mediatek.com>; linux-arm-kernel@lists.infradead.org; linux-media@vger.kernel.org
> Subject: Re: [RFC,V2,2/2] media: i2c: Add Omnivision OV02A10 camera sensor driver
>
>
>
> On 7/4/19 4:46 PM, dongchun.zhu@mediatek.com wrote:
> > From: Dongchun Zhu <dongchun.zhu@mediatek.com>
> >
> > This patch adds a V4L2 sub-device driver for OV02A10 image sensor.
> > The OV02A10 is a 1/5" CMOS sensor from Omnivision.
> > Supports output format: 10-bit Raw.
> > The OV02A10 has a single MIPI lane interface and use the I2C bus for control and the CSI-2 bus for data.
> >
> > Signed-off-by: Dongchun Zhu <dongchun.zhu@mediatek.com>
> >
> snip
> > +
> > +/* MIPI color bar enable output */
> > +static const struct regval ov02a10_test_pattern_enable_regs[] = {
> > +{0xfd, 0x01},
> > +{0x0d, 0x00},
> > +{0xb6, 0x01},
> > +{0x01, 0x01},
> > +{0xfd, 0x01},
> > +{0xac, 0x01},
> > +{REG_NULL, 0x00}
> Actually, you can use ARRAY_SIZE to write the regs, the REG_NULL can be removed. However, it is not a problem.
> ...
> snip...
Thanks for kindly reminder.
It would remain, just as OV5695/OV2685 did.
> > +static int ov02a10_set_fmt(struct v4l2_subdev *sd,
> > + struct v4l2_subdev_pad_config *cfg,
> > + struct v4l2_subdev_format *fmt) {
> > +struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format;
> > +int ret = 0;
> > +
> > +mutex_lock(&ov02a10->mutex);
> > +
> > +if (ov02a10->streaming) {
> > +ret = -EBUSY;
> > +goto unlock;
> I like return -EBUSY directly after mutex_unlock here and return 0 below.
Got it.
Fixed in next release.
> > +}
> > +
> > +/* only one mode supported */
> > +mbus_fmt->code = ov02a10->fmt.code;
> > +ov02a10_fill_fmt(ov02a10->cur_mode, mbus_fmt);
> > +ov02a10->fmt = fmt->format;
> > +
> > +unlock:
> > +mutex_unlock(&ov02a10->mutex);
> > +
> > +return ret;
> > +}
> > +
> > +static int ov02a10_get_fmt(struct v4l2_subdev *sd,
> > + struct v4l2_subdev_pad_config *cfg,
> > + struct v4l2_subdev_format *fmt) {
> > +struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format;
> > +
> > +mutex_lock(&ov02a10->mutex);
> > +
> > +fmt->format = ov02a10->fmt;
> > +mbus_fmt->code = ov02a10->fmt.code;
> > +ov02a10_fill_fmt(ov02a10->cur_mode, mbus_fmt);
> > +
> > +mutex_unlock(&ov02a10->mutex);
> > +
> > +return 0;
> > +}
> > +
> > +static int ov02a10_enum_mbus_code(struct v4l2_subdev *sd,
> > + struct v4l2_subdev_pad_config *cfg,
> > + struct v4l2_subdev_mbus_code_enum *code) {
> > +struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +
> > +if (code->index >= ARRAY_SIZE(supported_modes) || !(code->index))
> > +return -EINVAL;
> > +
> > +code->code = ov02a10->fmt.code;
> > +
> > +return 0;
> > +}
> > +
> > +static int ov02a10_enum_frame_sizes(struct v4l2_subdev *sd,
> > + struct v4l2_subdev_pad_config *cfg,
> > + struct v4l2_subdev_frame_size_enum *fse) {
> > +if (fse->index >= ARRAY_SIZE(supported_modes) || !(fse->index))
> > +return -EINVAL;
> > +
> > +fse->min_width = supported_modes[fse->index].width;
> > +fse->max_width = supported_modes[fse->index].width;
> > +fse->max_height = supported_modes[fse->index].height;
> > +fse->min_height = supported_modes[fse->index].height;
> > +
> > +return 0;
> > +}
> > +
> > +static int __ov02a10_power_on(struct ov02a10 *ov02a10) {
> > +struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
> > +struct device *dev = &client->dev;
> > +int ret;
> > +
> > +ret = clk_prepare_enable(ov02a10->xvclk);
> > +if (ret < 0) {
> > +dev_err(dev, "Failed to enable xvclk\n");
> > +return ret;
> > +}
> > +
> > +/* note: set 0 is high, set 1 is low */
> > +gpiod_set_value_cansleep(ov02a10->reset_gpio, 1);
> > +gpiod_set_value_cansleep(ov02a10->pwdn_gpio, 0);
> > +
> > +ret = regulator_bulk_enable(OV02A10_NUM_SUPPLIES, ov02a10->supplies);
> > +if (ret < 0) {
> > +dev_err(dev, "Failed to enable regulators\n");
> > +goto disable_clk;
> > +}
> > +msleep_range(7);
> > +
> > +gpiod_set_value_cansleep(ov02a10->pwdn_gpio, 1);
> > +msleep_range(10);
> > +
> > +gpiod_set_value_cansleep(ov02a10->reset_gpio, 0);
> > +msleep_range(10);
> > +
> > +return 0;
> > +
> > +disable_clk:
> > +clk_disable_unprepare(ov02a10->xvclk);
> > +
> > +return ret;
> > +}
> > +
> > +static void __ov02a10_power_off(struct ov02a10 *ov02a10) {
> > +clk_disable_unprepare(ov02a10->xvclk);
> > +gpiod_set_value_cansleep(ov02a10->reset_gpio, 1);
> > +gpiod_set_value_cansleep(ov02a10->pwdn_gpio, 1);
> > +regulator_bulk_disable(OV02A10_NUM_SUPPLIES, ov02a10->supplies); }
> > +
> > +static int __ov02a10_start_stream(struct ov02a10 *ov02a10) {
> > +struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
> > +int ret;
> > +
> > +/* Apply default values of current mode */
> > +ret = ov02a10_write_array(ov02a10, ov02a10->cur_mode->reg_list);
> > +if (ret)
> > +return ret;
> > +
> > +/* Apply customized values from user */
> > +ret = __v4l2_ctrl_handler_setup(ov02a10->subdev.ctrl_handler);
> > +if (ret)
> > +return ret;
> > +
> > +/* Set Orientation be 180 degree */
> Set orientation to 180 degree
Got it.
Fixed in next release.
> > +if (ov02a10->upside_down) {
> > +ret = ov02a10_write_reg(ov02a10, REG_MIRROR_FLIP_CONTROL,
> > +REG_CONFIG_MIRROR_FLIP);
> > +if (ret) {
> > +dev_err(&client->dev, "%s failed to set orientation\n",
> > +__func__);
> > +return ret;
> > +}
> > +ret = ov02a10_write_reg(ov02a10, REG_GLOBAL_EFFECTIVE,
> > +REG_ENABLE);
> > +if (ret < 0)
> > +return ret;
> > +}
> > +
> > +/* set stream on register */
> > +return ov02a10_write_reg(ov02a10,
> > + REG_SC_CTRL_MODE, SC_CTRL_MODE_STREAMING); }
> > +
> > +static int __ov02a10_stop_stream(struct ov02a10 *ov02a10) {
> > +return ov02a10_write_reg(ov02a10,
> > + REG_SC_CTRL_MODE, SC_CTRL_MODE_STANDBY); }
> > +
> > +static int ov02a10_entity_init_cfg(struct v4l2_subdev *subdev,
> > + struct v4l2_subdev_pad_config *cfg) {
> > +struct v4l2_subdev_format fmt = { 0 };
> > +
> > +fmt.which = cfg ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
> > +fmt.format.width = 1600;
> > +fmt.format.height = 1200;
> > +
> > +ov02a10_set_fmt(subdev, cfg, &fmt);
> > +
> > +return 0;
> > +}
> > +
> > +static int ov02a10_s_stream(struct v4l2_subdev *sd, int on) {
> > +struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
> > +int ret = 0;
> > +
> > +dev_dbg(&client->dev, "ov02a10 s_stream (%d)\n", on);
> > +mutex_lock(&ov02a10->mutex);
> > +
> > +if (ov02a10->streaming == on)
> > +goto unlock_and_return;
> > +
> > +if (on) {
> > +ret = pm_runtime_get_sync(&client->dev);
> > +if (ret < 0) {
> > +pm_runtime_put_noidle(&client->dev);
> > +goto unlock_and_return;
> > +}
> > +
> > +ret = __ov02a10_start_stream(ov02a10);
> > +if (ret) {
> > +__ov02a10_stop_stream(ov02a10);
> > +ov02a10->streaming = !on;
> > +goto err_rpm_put;
> > +}
> > +} else {
> > +__ov02a10_stop_stream(ov02a10);
> > +pm_runtime_put(&client->dev);
> > +}
> > +
> > +ov02a10->streaming = on;
> > +mutex_unlock(&ov02a10->mutex);
> > +
> > +return ret;
> > +
> > +err_rpm_put:
> > +pm_runtime_put(&client->dev);
> > +unlock_and_return:
> > +mutex_unlock(&ov02a10->mutex);
> > +
> > +return ret;
> > +}
> > +
> > +static int ov02a10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh
> > +*fh) {
> > +struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_get_try_format(sd,
> > +fh->pad,
> > +0);
> > +
> > +mutex_lock(&ov02a10->mutex);
> > +/* Initialize try_fmt */
> > +try_fmt->code = ov02a10->fmt.code;
> > +ov02a10_fill_fmt(&supported_modes[0], try_fmt);
> > +
> > +mutex_unlock(&ov02a10->mutex);
> > +
> > +return 0;
> > +}
> > +
> > +static int __maybe_unused ov02a10_runtime_resume(struct device *dev)
> > +{
> > +struct i2c_client *client = to_i2c_client(dev);
> > +struct v4l2_subdev *sd = i2c_get_clientdata(client);
> > +struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +
> > +return __ov02a10_power_on(ov02a10);
> > +}
> > +
> > +static int __maybe_unused ov02a10_runtime_suspend(struct device *dev)
> > +{
> > +struct i2c_client *client = to_i2c_client(dev);
> > +struct v4l2_subdev *sd = i2c_get_clientdata(client);
> > +struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +
> > +__ov02a10_power_off(ov02a10);
> > +
> > +return 0;
> > +}
> > +
> > +static const struct dev_pm_ops ov02a10_pm_ops = {
> > +SET_RUNTIME_PM_OPS(ov02a10_runtime_suspend,
> > + ov02a10_runtime_resume, NULL)
> > +};
> > +
> > +static int ov02a10_set_test_pattern(struct ov02a10 *ov02a10, s32
> > +value) {
> > +if (value)
> > +return ov02a10_write_array(ov02a10,
> > + ov02a10_test_pattern_enable_regs);
> > +
> > +return ov02a10_write_array(ov02a10,
> > +ov02a10_test_pattern_disable_regs);
> > +}
> > +
> > +static int ov02a10_set_ctrl(struct v4l2_ctrl *ctrl) {
> > +struct ov02a10 *ov02a10 = container_of(ctrl->handler,
> > + struct ov02a10, ctrl_handler);
> > +struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
> > +s64 max_expo;
> > +int ret;
> > +
> > +/* Propagate change of current control to all related controls */
> > +if (ctrl->id == V4L2_CID_VBLANK) {
> > +/* Update max exposure while meeting expected vblanking */
> > +max_expo = ov02a10->cur_mode->height + ctrl->val - 4;
> > +__v4l2_ctrl_modify_range(ov02a10->exposure,
> > + ov02a10->exposure->minimum, max_expo,
> > + ov02a10->exposure->step,
> > + ov02a10->exposure->default_value);
> > +}
> > +
> > +/* V4L2 controls values will be applied only when power is already up */
> > +if (!pm_runtime_get_if_in_use(&client->dev))
> > +return 0;
> > +
> > +switch (ctrl->id) {
> > +case V4L2_CID_EXPOSURE:
> > +ret = ov02a10_write_reg(ov02a10, REG_PAGE_SWITCH, REG_ENABLE);
> > +if (ret < 0)
> > +return ret;
> > +ret = ov02a10_write_reg(ov02a10, OV02A10_REG_EXPOSURE_H,
> > +((ctrl->val >> 8) & 0xFF));
> > +if (!ret) {
> > +ret = ov02a10_write_reg(ov02a10, OV02A10_REG_EXPOSURE_L,
> > +(ctrl->val & 0xFF));
> > +if (ret < 0)
> > +return ret;
> > +}
> > +ret = ov02a10_write_reg(ov02a10, REG_GLOBAL_EFFECTIVE,
> > +REG_ENABLE);
> > +if (ret < 0)
> > +return ret;
> > +break;
> > +case V4L2_CID_ANALOGUE_GAIN:
> > +ret = ov02a10_write_reg(ov02a10, REG_PAGE_SWITCH, REG_ENABLE);
> > +if (ret < 0)
> > +return ret;
> > +ret = ov02a10_write_reg(ov02a10, OV02A10_REG_GAIN,
> > +(ctrl->val & 0xFF));
> > +if (ret < 0)
> > +return ret;
> > +ret = ov02a10_write_reg(ov02a10, REG_GLOBAL_EFFECTIVE,
> > +REG_ENABLE);
> > +if (ret < 0)
> > +return ret;
> > +break;
> > +case V4L2_CID_VBLANK:
> > +ret = ov02a10_write_reg(ov02a10, REG_PAGE_SWITCH, REG_ENABLE);
> > +if (ret < 0)
> > +return ret;
> > +ret = ov02a10_write_reg(ov02a10, OV02A10_REG_VTS_H,
> > +(((ctrl->val +
> > +ov02a10->cur_mode->height - 1224) >> 8)
> > +& 0xFF));
> 1224 is hard-coded here, could you add some comments? Is it a sensor setting sensitive value?
This would be fixed in next release.
1224 is the basic line for OV02a10 CMOS sensor.
In fact, there is one relationship between framelength and v-blanking.
That is, framelength = basic_line + v-blanking.
Thus we could modify the value of v-blanking register to update
framelength.
> > +if (!ret) {
> > +ret = ov02a10_write_reg(ov02a10, OV02A10_REG_VTS_L,
> > +((ctrl->val +
> > +ov02a10->cur_mode->height -
> > +1224) & 0xFF));
> ditto.
Fixed in next release.
> > +if (ret < 0)
> > +return ret;
> > +}
> > +ret = ov02a10_write_reg(ov02a10, REG_GLOBAL_EFFECTIVE,
> > +REG_ENABLE);
> > +if (ret < 0)
> > +return ret;
> > +break;
> > +case V4L2_CID_TEST_PATTERN:
> > +ret = ov02a10_set_test_pattern(ov02a10, ctrl->val);
> > +if (ret < 0)
> > +return ret;
> > +break;
> > +default:
> > +dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
> > + __func__, ctrl->id, ctrl->val);
> > +ret = -EINVAL;
> > +break;
> > +};
> > +
> > +pm_runtime_put(&client->dev);
> > +
> > +return ret;
> > +}
> > +
> > +static const struct v4l2_subdev_video_ops ov02a10_video_ops = {
> > +.s_stream = ov02a10_s_stream,
> > +};
> > +
> > +static const struct v4l2_subdev_pad_ops ov02a10_pad_ops = {
> > +.init_cfg = ov02a10_entity_init_cfg,
> > +.enum_mbus_code = ov02a10_enum_mbus_code,
> > +.enum_frame_size = ov02a10_enum_frame_sizes,
> > +.get_fmt = ov02a10_get_fmt,
> > +.set_fmt = ov02a10_set_fmt,
> > +};
> > +
> > +static const struct v4l2_subdev_ops ov02a10_subdev_ops = {
> > +.video= &ov02a10_video_ops,
> > +.pad= &ov02a10_pad_ops,
> > +};
> > +
> > +static const struct media_entity_operations ov02a10_subdev_entity_ops = {
> > +.link_validate = v4l2_subdev_link_validate, };
> > +
> > +static const struct v4l2_subdev_internal_ops ov02a10_internal_ops = {
> > +.open = ov02a10_open,
> > +};
> > +
> > +static const struct v4l2_ctrl_ops ov02a10_ctrl_ops = {
> > +.s_ctrl = ov02a10_set_ctrl,
> > +};
> > +
> > +static int ov02a10_initialize_controls(struct ov02a10 *ov02a10) {
> > +struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
> > +const struct ov02a10_mode *mode;
> > +struct v4l2_ctrl_handler *handler;
> > +struct v4l2_ctrl *ctrl;
> > +u64 exposure_max;
> > +u32 pixel_rate, h_blank;
> > +int ret;
> > +
> > +handler = &ov02a10->ctrl_handler;
> > +mode = ov02a10->cur_mode;
> > +ret = v4l2_ctrl_handler_init(handler, 10);
> > +if (ret)
> > +return ret;
> > +handler->lock = &ov02a10->mutex;
> > +
> > +ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
> > + 0, 0, link_freq_menu_items);
> > +if (ctrl)
> > +ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > +
> > +pixel_rate = (link_freq_menu_items[0] * 2 * OV02A10_LANES) /
> > + OV02A10_BITS_PER_SAMPLE;
> > +v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
> > + 0, pixel_rate, 1, pixel_rate);
> > +
> > +h_blank = mode->hts_def - mode->width;
> > +ov02a10->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
> > + h_blank, h_blank, 1, h_blank);
> > +if (ov02a10->hblank)
> > +ov02a10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > +
> > +ov02a10->vblank = v4l2_ctrl_new_std(handler, &ov02a10_ctrl_ops,
> > + V4L2_CID_VBLANK, mode->vts_def -
> > + mode->height,
> > + OV02A10_VTS_MAX - mode->height, 1,
> > + mode->vts_def - mode->height);
> > +
> > +exposure_max = mode->vts_def - 4;
> > +ov02a10->exposure = v4l2_ctrl_new_std(handler, &ov02a10_ctrl_ops,
> > + V4L2_CID_EXPOSURE,
> > + OV02A10_EXPOSURE_MIN,
> > + exposure_max,
> > + OV02A10_EXPOSURE_STEP,
> > + mode->exp_def);
> > +
> > +ov02a10->anal_gain = v4l2_ctrl_new_std(handler, &ov02a10_ctrl_ops,
> > + V4L2_CID_ANALOGUE_GAIN,
> > + OV02A10_GAIN_MIN,
> > + OV02A10_GAIN_MAX,
> > + OV02A10_GAIN_STEP,
> > + OV02A10_GAIN_DEFAULT);
> > +
> > +ov02a10->test_pattern =
> > + v4l2_ctrl_new_std_menu_items(handler,
> > +&ov02a10_ctrl_ops,
> > +V4L2_CID_TEST_PATTERN,
> > +ARRAY_SIZE(ov02a10_test_pattern_menu) -
> > +1, 0, 0, ov02a10_test_pattern_menu);
> > +
> > +if (handler->error) {
> > +ret = handler->error;
> > +dev_err(&client->dev,
> > +"Failed to init controls(%d)\n", ret);
> > +goto err_free_handler;
> > +}
> > +
> > +ov02a10->subdev.ctrl_handler = handler;
> > +
> > +return 0;
> > +
> > +err_free_handler:
> > +v4l2_ctrl_handler_free(handler);
> > +
> > +return ret;
> > +}
> > +
> > +static int ov02a10_check_sensor_id(struct ov02a10 *ov02a10) {
> > +struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
> > +u16 id;
> > +u8 pid = 0;
> > +u8 ver = 0;
> > +int ret;
> > +
> > +/* Check sensor revision */
> > +ret = ov02a10_read_reg(ov02a10, OV02A10_REG_CHIP_ID_H, &pid);
> > +if (ret)
> > +return ret;
> > +
> > +ret = ov02a10_read_reg(ov02a10, OV02A10_REG_CHIP_ID_L, &ver);
> > +if (ret)
> > +return ret;
> > +
> > +id = OV02A10_ID(pid, ver);
> > +if (id != CHIP_ID) {
> > +dev_err(&client->dev, "Unexpected sensor id(%04x)\n", id);
> > +return ret;
> > +}
> > +dev_dbg(&client->dev, "Detected OV%04X sensor\n", id);
> > +
> > +return 0;
> > +}
> > +
> > +static int ov02a10_configure_regulators(struct ov02a10 *ov02a10) {
> > +struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
> > +unsigned int i;
> > +
> > +for (i = 0; i < OV02A10_NUM_SUPPLIES; i++)
> > +ov02a10->supplies[i].supply = ov02a10_supply_names[i];
> > +
> > +return devm_regulator_bulk_get(&client->dev,
> > + OV02A10_NUM_SUPPLIES,
> > + ov02a10->supplies);
> > +}
> > +
> > +static int ov02a10_probe(struct i2c_client *client) {
> > +struct device *dev = &client->dev;
> > +struct ov02a10 *ov02a10;
> > +u32 rotation;
> > +u32 xclk_freq;
> > +int ret;
> > +
> > +dev_dbg(dev, "ov02a10 probe\n");
> I think this line is not needed at all.
Removed in next release.
> > +ov02a10 = devm_kzalloc(dev, sizeof(*ov02a10), GFP_KERNEL);
> > +if (!ov02a10)
> > +return -ENOMEM;
> > +
> > +v4l2_i2c_subdev_init(&ov02a10->subdev, client, &ov02a10_subdev_ops);
> > +ov02a10->fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
> > +
> > +/* optional indication of physical rotation of sensor */
> > +ret = fwnode_property_read_u32(dev_fwnode(dev), "rotation",
> > + &rotation);
> > +if (!ret) {
> > +switch (rotation) {
> > +case 180:
> > +ov02a10->upside_down = true;
> > +ov02a10->fmt.code = MEDIA_BUS_FMT_SRGGB10_1X10;
> > +break;
> > +case 0:
> > +break;
> > +default:
> > +dev_warn(dev, "%u degrees rotation is not supported, ignoring...\n",
> > + rotation);
> > +}
> > +}
> > +
> > +/* get system clock (xvclk) */
> > +ov02a10->xvclk = devm_clk_get(dev, "xvclk");
> > +if (IS_ERR(ov02a10->xvclk)) {
> > +dev_err(dev, "Failed to get xvclk\n");
> > +return -EINVAL;
> > +}
> > +
> > +ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);
> > +if (ret) {
> > +dev_err(dev, "Failed to get xclk frequency\n");
> > +return ret;
> > +}
> > +
> > +/* external clock must be 24MHz, allow 1% tolerance */
> > +if (xclk_freq < 23760000 || xclk_freq > 24240000) {
> > +dev_err(dev, "external clock frequency %u is not supported\n",
> > +xclk_freq);
> > +return -EINVAL;
> > +}
> > +dev_dbg(dev, "external clock frequency %u\n", xclk_freq);
> > +
> > +ret = clk_set_rate(ov02a10->xvclk, xclk_freq);
> > +if (ret) {
> > +dev_err(dev, "Failed to set xvclk frequency (24MHz)\n");
> > +return ret;
> > +}
> > +
> > +ov02a10->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
> > +if (IS_ERR(ov02a10->pwdn_gpio)) {
> > +dev_err(dev, "Failed to get powerdown-gpios\n");
> > +return -EINVAL;
> > +}
> > +
> > +ov02a10->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
> > +if (IS_ERR(ov02a10->reset_gpio)) {
> > +dev_err(dev, "Failed to get reset-gpios\n");
> > +return -EINVAL;
> > +}
> > +
> > +ret = ov02a10_configure_regulators(ov02a10);
> > +if (ret) {
> > +dev_err(dev, "Failed to get power regulators\n");
> > +return ret;
> > +}
> > +
> > +mutex_init(&ov02a10->mutex);
> > +ov02a10->cur_mode = &supported_modes[0];
> > +ret = ov02a10_initialize_controls(ov02a10);
> > +if (ret) {
> > +dev_err(dev, "Failed to initialize controls\n");
> > +goto err_destroy_mutex;
> > +}
> > +
> > +ret = __ov02a10_power_on(ov02a10);
> > +if (ret)
> > +goto err_free_handler;
> > +
> > +ret = ov02a10_check_sensor_id(ov02a10);
> > +if (ret)
> > +goto err_power_off;
> > +
> > +ov02a10->subdev.internal_ops = &ov02a10_internal_ops;
> > +ov02a10->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> > +ov02a10->subdev.entity.ops = &ov02a10_subdev_entity_ops;
> > +ov02a10->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
> > +ov02a10->pad.flags = MEDIA_PAD_FL_SOURCE;
> > +ret = media_entity_pads_init(&ov02a10->subdev.entity, 1, &ov02a10->pad);
> > +if (ret < 0) {
> > +dev_err(dev, "failed to init entity pads: %d", ret);
> > +goto err_power_off;
> > +}
> > +
> > +ret = v4l2_async_register_subdev(&ov02a10->subdev);
> > +if (ret) {
> > +dev_err(dev, "failed to register V4L2 subdev: %d",
> > +ret);
> > +goto err_clean_entity;
> > +}
> > +
> > +pm_runtime_set_active(dev);
> > +pm_runtime_enable(dev);
> > +pm_runtime_idle(dev);
> > +
> > +return 0;
> > +
> > +err_clean_entity:
> > +media_entity_cleanup(&ov02a10->subdev.entity);
> > +err_power_off:
> > +__ov02a10_power_off(ov02a10);
> > +err_free_handler:
> > +v4l2_ctrl_handler_free(ov02a10->subdev.ctrl_handler);
> > +err_destroy_mutex:
> > +mutex_destroy(&ov02a10->mutex);
> > +
> > +return ret;
> > +}
> > +
> > +static int ov02a10_remove(struct i2c_client *client) {
> > +struct v4l2_subdev *sd = i2c_get_clientdata(client);
> > +struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +
> > +v4l2_async_unregister_subdev(sd);
> > +media_entity_cleanup(&sd->entity);
> > +v4l2_ctrl_handler_free(sd->ctrl_handler);
> > +pm_runtime_disable(&client->dev);
> > +if (!pm_runtime_status_suspended(&client->dev))
> > +__ov02a10_power_off(ov02a10);
> > +pm_runtime_set_suspended(&client->dev);
> > +mutex_destroy(&ov02a10->mutex);
> > +
> > +return 0;
> > +}
> > +
> > +#if IS_ENABLED(CONFIG_OF)
> > +static const struct of_device_id ov02a10_of_match[] = {
> > +{ .compatible = "ovti,ov02a10" },
> > +{},
> > +};
> > +MODULE_DEVICE_TABLE(of, ov02a10_of_match); #endif
> > +
> > +static struct i2c_driver ov02a10_i2c_driver = {
> > +.driver = {
> > +.name = "ov02a10",
> > +.pm = &ov02a10_pm_ops,
> > +.of_match_table = ov02a10_of_match,
> > +},
> > +.probe_new= &ov02a10_probe,
> > +.remove= &ov02a10_remove,
> > +};
> > +
> > +module_i2c_driver(ov02a10_i2c_driver);
> > +
> > +MODULE_AUTHOR("Dongchun Zhu <dongchun.zhu@mediatek.com>");
> > +MODULE_DESCRIPTION("OmniVision OV02A10 sensor driver");
> > +MODULE_LICENSE("GPL v2");
> > +
> >
> Other part looks good to me.
Many thanks for your review.
I really appreciate the effort you all made for the work.
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
> *********************MEDIATEK Confidential/Internal Use*********************
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [Xen-devel] [PATCH 07/11] swiotlb-xen: provide a single page-coherent.h header
From: Christoph Hellwig @ 2019-08-17 6:50 UTC (permalink / raw)
To: Julien Grall
Cc: Stefano Stabellini, Konrad Rzeszutek Wilk, x86, linux-kernel,
iommu, xen-devel, Christoph Hellwig, linux-arm-kernel
In-Reply-To: <9a3261c6-5d92-cf6b-1ae8-3a8e8b5ef0d4@arm.com>
On Fri, Aug 16, 2019 at 11:40:43PM +0100, Julien Grall wrote:
> I am not sure I agree with this rename. The implementation of the helpers
> are very Arm specific as this is assuming Dom0 is 1:1 mapped.
>
> This was necessary due to the lack of IOMMU on Arm platforms back then.
> But this is now a pain to get rid of it on newer platform...
So if you look at the final version of the header after the whole
series, what assumes a 1:1 mapping? It all just is
if (pfn_valid())
local cache sync;
else
call into the arch code;
are you concerned that the local cache sync might have to be split
up more for a non-1:1 map in that case? We could just move
the xen_dma_* routines into the arch instead of __xen_dma, but it
really helps to have a common interface header.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V5 3/5] iommu/dma-iommu: Handle deferred devices
From: Tom Murphy @ 2019-08-17 7:19 UTC (permalink / raw)
To: Hillf Danton
Cc: Heiko Stuebner, virtualization, linux-tegra, Thierry Reding,
Will Deacon, Marek Szyprowski, Jean-Philippe Brucker,
linux-samsung-soc, Joerg Roedel, iommu, Krzysztof Kozlowski,
Jonathan Hunter, linux-rockchip, Andy Gross, Gerald Schaefer,
linux-s390, linux-arm-msm, linux-mediatek, Matthias Brugger,
linux-arm-kernel, David Woodhouse, Linux Kernel Mailing List,
Rob Clark, Kukjin Kim, Robin Murphy
In-Reply-To: <20190817033914.4812-1-hdanton@sina.com>
On Sat, 17 Aug 2019 at 04:39, Hillf Danton <hdanton@sina.com> wrote:
>
>
> On Thu, 15 Aug 2019 12:09:41 +0100 Tom Murphy wrote:
> >
> > Handle devices which defer their attach to the iommu in the dma-iommu api
> >
> > Signed-off-by: Tom Murphy <murphyt7@tcd.ie>
> > ---
> > drivers/iommu/dma-iommu.c | 27 ++++++++++++++++++++++++++-
> > 1 file changed, 26 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> > index 2712fbc68b28..906b7fa14d3c 100644
> > --- a/drivers/iommu/dma-iommu.c
> > +++ b/drivers/iommu/dma-iommu.c
> > @@ -22,6 +22,7 @@
> > #include <linux/pci.h>
> > #include <linux/scatterlist.h>
> > #include <linux/vmalloc.h>
> > +#include <linux/crash_dump.h>
> >
> > struct iommu_dma_msi_page {
> > struct list_head list;
> > @@ -351,6 +352,21 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
> > return iova_reserve_iommu_regions(dev, domain);
> > }
> >
> > +static int handle_deferred_device(struct device *dev,
> > + struct iommu_domain *domain)
> > +{
> > + const struct iommu_ops *ops = domain->ops;
> > +
> > + if (!is_kdump_kernel())
> > + return 0;
> > +
> > + if (unlikely(ops->is_attach_deferred &&
> > + ops->is_attach_deferred(domain, dev)))
> > + return iommu_attach_device(domain, dev);
> > +
> > + return 0;
> > +}
> > +
> > /**
> > * dma_info_to_prot - Translate DMA API directions and attributes to IOMMU API
> > * page flags.
> > @@ -463,6 +479,9 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
> > size_t iova_off = iova_offset(iovad, phys);
> > dma_addr_t iova;
> >
> > + if (unlikely(handle_deferred_device(dev, domain)))
> > + return DMA_MAPPING_ERROR;
> > +
> > size = iova_align(iovad, size + iova_off);
> >
> > iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
>
> iommu_map_atomic() is applied to __iommu_dma_map() in 2/5.
> Is it an atomic context currently given the mutex_lock() in
> iommu_attach_device()?
I don't see your point here. __iommu_dma_map isn't called from
iommu_attach_device, why would we care about a mutex in
iommu_attach_device?
__iommu_dma_map can be called from an atomic context (it isn't always
but it does happen). __iommu_dma_map is called by iommu_dma_alloc
which implements the iommu_dma_ops::alloc function which by design
needs to be callable from an atomic context. Does that answer your
question?
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* generic ioremap (and lots of cleanups)
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
Hi all,
the last patches in this series add a generic ioremap implementation,
and switch our 3 most recent and thus most tidy architeture ports over
to use it. With a little work and an additional arch hook or two the
implementation should be able to eventually cover more than half of
our ports.
The patches before that clean up various lose ends in the ioremap
and iounmap implementations.
A git tree is also available here:
git://git.infradead.org/users/hch/misc.git generic-ioremap
Gitweb:
http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/generic-ioremap
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 01/26] mtd/maps/pxa2xx: use ioremap_cache insted of ioremap_cached
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
pxa2xx-flash is the only user of ioremap_cached, which is an alias
for ioremap_cache anyway.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/mtd/maps/pxa2xx-flash.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index cebb346877a9..7d96758a8f04 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -68,8 +68,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
info->map.name);
return -ENOMEM;
}
- info->map.cached =
- ioremap_cached(info->map.phys, info->map.size);
+ info->map.cached = ioremap_cache(info->map.phys, info->map.size);
if (!info->map.cached)
printk(KERN_WARNING "Failed to ioremap cached %s\n",
info->map.name);
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH V2 08/13] i2c: bcm2835: Avoid clk stretch quirk for BCM2711
From: Stefan Wahren @ 2019-08-17 7:32 UTC (permalink / raw)
To: Wolfram Sang
Cc: Mark Rutland, devicetree, Florian Fainelli, Scott Branden,
Stephen Boyd, Ray Jui, Michael Turquette, Eric Anholt,
Rob Herring, bcm-kernel-feedback-list, linux-i2c, linux-clk,
linux-arm-kernel, linux-rpi-kernel
In-Reply-To: <20190814193628.GA9756@kunai>
Hi Wolfram,
Am 14.08.19 um 21:36 schrieb Wolfram Sang:
>> static const struct of_device_id bcm2835_i2c_of_match[] = {
>> - { .compatible = "brcm,bcm2835-i2c" },
>> + { .compatible = "brcm,bcm2711-i2c", .data = (void *)NO_STRETCH_BUG },
>> + { .compatible = "brcm,bcm2835-i2c", .data = (void *)STRETCH_BUG },
> What about simply putting a pointer to the quirks data (or NULL) as
> match_data? Then the code should be:
>
> adap->quirks = (cast)of_device_get_match_data(&pdev->dev);
quirks = (const struct i2c_adapter_quirks *)of_device_get_match_data(dev);
would hit the line limit. Do you insists on the cast, because it's
actually not required?
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 02/26] arm, unicore32: remove ioremap_cached
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
No users of ioremap_cached are left, remove it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/arm/include/asm/io.h | 6 ------
arch/arm/mm/ioremap.c | 4 ----
arch/arm/mm/mmu.c | 2 +-
arch/arm/mm/nommu.c | 4 ----
arch/unicore32/include/asm/io.h | 4 +---
arch/unicore32/mm/ioremap.c | 8 --------
6 files changed, 2 insertions(+), 26 deletions(-)
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 7a0596fcb2e7..924f9dd502ed 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -400,12 +400,6 @@ void __iomem *ioremap(resource_size_t res_cookie, size_t size);
void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size);
#define ioremap_cache ioremap_cache
-/*
- * Do not use ioremap_cached in new code. Provided for the benefit of
- * the pxa2xx-flash MTD driver only.
- */
-void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size);
-
void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size);
#define ioremap_wc ioremap_wc
#define ioremap_wt ioremap_wc
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index d42b93316183..72286f9a4d30 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -382,15 +382,11 @@ void __iomem *ioremap(resource_size_t res_cookie, size_t size)
EXPORT_SYMBOL(ioremap);
void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size)
- __alias(ioremap_cached);
-
-void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size)
{
return arch_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED,
__builtin_return_address(0));
}
EXPORT_SYMBOL(ioremap_cache);
-EXPORT_SYMBOL(ioremap_cached);
void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
{
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index d9a0038774a6..ed08afc3f5e5 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -259,7 +259,7 @@ static struct mem_type mem_types[] __ro_after_init = {
.prot_sect = PROT_SECT_DEVICE,
.domain = DOMAIN_IO,
},
- [MT_DEVICE_CACHED] = { /* ioremap_cached */
+ [MT_DEVICE_CACHED] = { /* ioremap_cache */
.prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_CACHED,
.prot_l1 = PMD_TYPE_TABLE,
.prot_sect = PROT_SECT_DEVICE | PMD_SECT_WB,
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 24ecf8d30a1e..8b3d7191e2b8 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -206,15 +206,11 @@ void __iomem *ioremap(resource_size_t res_cookie, size_t size)
EXPORT_SYMBOL(ioremap);
void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size)
- __alias(ioremap_cached);
-
-void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size)
{
return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED,
__builtin_return_address(0));
}
EXPORT_SYMBOL(ioremap_cache);
-EXPORT_SYMBOL(ioremap_cached);
void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
{
diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
index c71aa4b95996..4b460e01acfa 100644
--- a/arch/unicore32/include/asm/io.h
+++ b/arch/unicore32/include/asm/io.h
@@ -18,10 +18,9 @@
#include <asm-generic/io.h>
/*
- * __uc32_ioremap and __uc32_ioremap_cached takes CPU physical address.
+ * __uc32_ioremap takes CPU physical address.
*/
extern void __iomem *__uc32_ioremap(unsigned long, size_t);
-extern void __iomem *__uc32_ioremap_cached(unsigned long, size_t);
extern void __uc32_iounmap(volatile void __iomem *addr);
/*
@@ -32,7 +31,6 @@ extern void __uc32_iounmap(volatile void __iomem *addr);
*
*/
#define ioremap(cookie, size) __uc32_ioremap(cookie, size)
-#define ioremap_cached(cookie, size) __uc32_ioremap_cached(cookie, size)
#define ioremap_nocache(cookie, size) __uc32_ioremap(cookie, size)
#define iounmap(cookie) __uc32_iounmap(cookie)
diff --git a/arch/unicore32/mm/ioremap.c b/arch/unicore32/mm/ioremap.c
index cf6d656f240c..46a64bd6156a 100644
--- a/arch/unicore32/mm/ioremap.c
+++ b/arch/unicore32/mm/ioremap.c
@@ -220,14 +220,6 @@ __uc32_ioremap(unsigned long phys_addr, size_t size)
}
EXPORT_SYMBOL(__uc32_ioremap);
-void __iomem *
-__uc32_ioremap_cached(unsigned long phys_addr, size_t size)
-{
- return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE_CACHED,
- __builtin_return_address(0));
-}
-EXPORT_SYMBOL(__uc32_ioremap_cached);
-
void __uc32_iounmap(volatile void __iomem *io_addr)
{
void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 03/26] m68k, microblaze: remove ioremap_fullcache
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
No callers of this function.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/m68k/include/asm/kmap.h | 7 -------
arch/microblaze/include/asm/io.h | 1 -
2 files changed, 8 deletions(-)
diff --git a/arch/m68k/include/asm/kmap.h b/arch/m68k/include/asm/kmap.h
index aac7f045f7f0..03d904fe6087 100644
--- a/arch/m68k/include/asm/kmap.h
+++ b/arch/m68k/include/asm/kmap.h
@@ -43,13 +43,6 @@ static inline void __iomem *ioremap_wt(unsigned long physaddr,
return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
}
-#define ioremap_fullcache ioremap_fullcache
-static inline void __iomem *ioremap_fullcache(unsigned long physaddr,
- unsigned long size)
-{
- return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
-}
-
#define memset_io memset_io
static inline void memset_io(volatile void __iomem *addr, unsigned char val,
int count)
diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h
index c7968139486f..86c95b2a1ce1 100644
--- a/arch/microblaze/include/asm/io.h
+++ b/arch/microblaze/include/asm/io.h
@@ -40,7 +40,6 @@ extern void iounmap(volatile void __iomem *addr);
extern void __iomem *ioremap(phys_addr_t address, unsigned long size);
#define ioremap_nocache(addr, size) ioremap((addr), (size))
-#define ioremap_fullcache(addr, size) ioremap((addr), (size))
#define ioremap_wc(addr, size) ioremap((addr), (size))
#define ioremap_wt(addr, size) ioremap((addr), (size))
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 04/26] mips: remove ioremap_cachable
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
Just define ioremap_cache directly.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/mips/include/asm/io.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 97a280640daf..c02db986ddf5 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -262,11 +262,11 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset,
#define ioremap_uc ioremap_nocache
/*
- * ioremap_cachable - map bus memory into CPU space
+ * ioremap_cache - map bus memory into CPU space
* @offset: bus address of the memory
* @size: size of the resource to map
*
- * ioremap_nocache performs a platform specific sequence of operations to
+ * ioremap_cache performs a platform specific sequence of operations to
* make bus memory CPU accessible via the readb/readw/readl/writeb/
* writew/writel functions and the other mmio helpers. The returned
* address is not guaranteed to be usable directly as a virtual
@@ -276,9 +276,8 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset,
* the CPU. Also enables full write-combining. Useful for some
* memory-like regions on I/O busses.
*/
-#define ioremap_cachable(offset, size) \
+#define ioremap_cache(offset, size) \
__ioremap_mode((offset), (size), _page_cachable_default)
-#define ioremap_cache ioremap_cachable
/*
* ioremap_wc - map bus memory into CPU space
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 05/26] openrisc: map as uncached in ioremap
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
Openrisc is the only architecture not mapping ioremap as uncached,
which has been the default since the Linux 2.6.x days. Switch it
over to implement uncached semantics by default.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/openrisc/include/asm/io.h | 20 +++-----------------
arch/openrisc/include/asm/pgtable.h | 2 +-
arch/openrisc/mm/ioremap.c | 8 ++++----
3 files changed, 8 insertions(+), 22 deletions(-)
diff --git a/arch/openrisc/include/asm/io.h b/arch/openrisc/include/asm/io.h
index 06a710757789..5b81a96ab85e 100644
--- a/arch/openrisc/include/asm/io.h
+++ b/arch/openrisc/include/asm/io.h
@@ -25,25 +25,11 @@
#define PIO_OFFSET 0
#define PIO_MASK 0
-#define ioremap_nocache ioremap_nocache
+#define ioremap_nocache ioremap
#include <asm-generic/io.h>
#include <asm/pgtable.h>
-extern void __iomem *__ioremap(phys_addr_t offset, unsigned long size,
- pgprot_t prot);
-
-static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
-{
- return __ioremap(offset, size, PAGE_KERNEL);
-}
-
-/* #define _PAGE_CI 0x002 */
-static inline void __iomem *ioremap_nocache(phys_addr_t offset,
- unsigned long size)
-{
- return __ioremap(offset, size,
- __pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_CI));
-}
-
+void __iomem *ioremap(phys_addr_t offset, unsigned long size);
extern void iounmap(void *addr);
+
#endif
diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h
index 497fd908a4c4..2fe9ff5b5d6f 100644
--- a/arch/openrisc/include/asm/pgtable.h
+++ b/arch/openrisc/include/asm/pgtable.h
@@ -97,7 +97,7 @@ extern void paging_init(void);
/* Define some higher level generic page attributes.
*
* If you change _PAGE_CI definition be sure to change it in
- * io.h for ioremap_nocache() too.
+ * io.h for ioremap() too.
*/
/*
diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c
index e0c551ca0891..8f8e97f7eac9 100644
--- a/arch/openrisc/mm/ioremap.c
+++ b/arch/openrisc/mm/ioremap.c
@@ -34,8 +34,7 @@ static unsigned int fixmaps_used __initdata;
* have to convert them into an offset in a page-aligned mapping, but the
* caller shouldn't need to know that small detail.
*/
-void __iomem *__ref
-__ioremap(phys_addr_t addr, unsigned long size, pgprot_t prot)
+void __iomem *__ref ioremap(phys_addr_t addr, unsigned long size)
{
phys_addr_t p;
unsigned long v;
@@ -66,7 +65,8 @@ __ioremap(phys_addr_t addr, unsigned long size, pgprot_t prot)
fixmaps_used += (size >> PAGE_SHIFT);
}
- if (ioremap_page_range(v, v + size, p, prot)) {
+ if (ioremap_page_range(v, v + size, p,
+ __pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_CI))) {
if (likely(mem_init_done))
vfree(area->addr);
else
@@ -76,7 +76,7 @@ __ioremap(phys_addr_t addr, unsigned long size, pgprot_t prot)
return (void __iomem *)(offset + (char *)v);
}
-EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(ioremap);
void iounmap(void *addr)
{
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 06/26] ia64: rename ioremap_nocache to ioremap_uc
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
On ia64 ioremap_nocache fails if attributs don't match. Not other
architectures does this, and we plan to get rid of ioremap_nocache.
So get rid of the special semantics and define ioremap_nocache in
terms of ioremap as no portable driver could rely on the behavior
anyway.
However x86 implements ioremap_uc with a in a similar way as the ia64
version of ioremap_nocache, so implement that instead.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/ia64/include/asm/io.h | 6 +++---
arch/ia64/mm/ioremap.c | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index a511d62d447a..febd2c6ea0b4 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -412,16 +412,16 @@ __writeq (unsigned long val, volatile void __iomem *addr)
# ifdef __KERNEL__
extern void __iomem * ioremap(unsigned long offset, unsigned long size);
-extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
+extern void __iomem * ioremap_uc(unsigned long offset, unsigned long size);
extern void iounmap (volatile void __iomem *addr);
static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size)
{
return ioremap(phys_addr, size);
}
#define ioremap ioremap
-#define ioremap_nocache ioremap_nocache
+#define ioremap_nocache ioremap
#define ioremap_cache ioremap_cache
-#define ioremap_uc ioremap_nocache
+#define ioremap_uc ioremap_uc
#define iounmap iounmap
/*
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 0c0de2c4ec69..a09cfa064536 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -99,14 +99,14 @@ ioremap (unsigned long phys_addr, unsigned long size)
EXPORT_SYMBOL(ioremap);
void __iomem *
-ioremap_nocache (unsigned long phys_addr, unsigned long size)
+ioremap_uc(unsigned long phys_addr, unsigned long size)
{
if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
return NULL;
return __ioremap_uc(phys_addr);
}
-EXPORT_SYMBOL(ioremap_nocache);
+EXPORT_SYMBOL(ioremap_uc);
void
early_iounmap (volatile void __iomem *addr, unsigned long size)
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 07/26] hexagon: clean up ioremap
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
Use ioremap as the main implemented function, and defined
ioremap_nocache to it as a deprecated alias.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/hexagon/include/asm/io.h | 11 ++---------
arch/hexagon/kernel/hexagon_ksyms.c | 2 +-
arch/hexagon/mm/ioremap.c | 2 +-
3 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
index ba1a444d55b3..89537dc1cf97 100644
--- a/arch/hexagon/include/asm/io.h
+++ b/arch/hexagon/include/asm/io.h
@@ -171,16 +171,9 @@ static inline void writel(u32 data, volatile void __iomem *addr)
#define writew_relaxed __raw_writew
#define writel_relaxed __raw_writel
-/*
- * Need an mtype somewhere in here, for cache type deals?
- * This is probably too long for an inline.
- */
-void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+void __iomem *ioremap(unsigned long phys_addr, unsigned long size);
+#define ioremap_nocache ioremap
-static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
-{
- return ioremap_nocache(phys_addr, size);
-}
static inline void iounmap(volatile void __iomem *addr)
{
diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c
index cf8974beb500..b3dbb472572e 100644
--- a/arch/hexagon/kernel/hexagon_ksyms.c
+++ b/arch/hexagon/kernel/hexagon_ksyms.c
@@ -20,7 +20,7 @@ EXPORT_SYMBOL(__vmgetie);
EXPORT_SYMBOL(__vmsetie);
EXPORT_SYMBOL(__vmyield);
EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(ioremap_nocache);
+EXPORT_SYMBOL(ioremap);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
diff --git a/arch/hexagon/mm/ioremap.c b/arch/hexagon/mm/ioremap.c
index 77d8e1e69e9b..b103d83b5fbb 100644
--- a/arch/hexagon/mm/ioremap.c
+++ b/arch/hexagon/mm/ioremap.c
@@ -9,7 +9,7 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
-void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size)
+void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
{
unsigned long last_addr, addr;
unsigned long offset = phys_addr & ~PAGE_MASK;
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 08/26] m68k: simplify ioremap_nocache
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
Just define ioremap_nocache to ioremap instead of duplicating the
inline. Also defined ioremap_uc in terms of ioremap instead of
the using a double indirection.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/m68k/include/asm/kmap.h | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/arch/m68k/include/asm/kmap.h b/arch/m68k/include/asm/kmap.h
index 03d904fe6087..421b6c9c769d 100644
--- a/arch/m68k/include/asm/kmap.h
+++ b/arch/m68k/include/asm/kmap.h
@@ -28,14 +28,8 @@ static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-#define ioremap_nocache ioremap_nocache
-static inline void __iomem *ioremap_nocache(unsigned long physaddr,
- unsigned long size)
-{
- return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
-}
-
-#define ioremap_uc ioremap_nocache
+#define ioremap_nocache ioremap
+#define ioremap_uc ioremap
#define ioremap_wt ioremap_wt
static inline void __iomem *ioremap_wt(unsigned long physaddr,
unsigned long size)
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 09/26] alpha: remove the unused __ioremap wrapper
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
No need for the additional namespace pollution.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/alpha/include/asm/io.h | 6 ------
1 file changed, 6 deletions(-)
diff --git a/arch/alpha/include/asm/io.h b/arch/alpha/include/asm/io.h
index af2c0063dc75..1989b946a28d 100644
--- a/arch/alpha/include/asm/io.h
+++ b/arch/alpha/include/asm/io.h
@@ -283,12 +283,6 @@ static inline void __iomem *ioremap(unsigned long port, unsigned long size)
return IO_CONCAT(__IO_PREFIX,ioremap) (port, size);
}
-static inline void __iomem *__ioremap(unsigned long port, unsigned long size,
- unsigned long flags)
-{
- return ioremap(port, size);
-}
-
static inline void __iomem * ioremap_nocache(unsigned long offset,
unsigned long size)
{
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 10/26] nios2: remove __ioremap
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
The cacheflag argument to __ioremap is always 0, so just implement
ioremap directly.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/nios2/include/asm/io.h | 20 ++++----------------
arch/nios2/mm/ioremap.c | 17 +++--------------
2 files changed, 7 insertions(+), 30 deletions(-)
diff --git a/arch/nios2/include/asm/io.h b/arch/nios2/include/asm/io.h
index 9010243077ab..74ab34aa6731 100644
--- a/arch/nios2/include/asm/io.h
+++ b/arch/nios2/include/asm/io.h
@@ -25,29 +25,17 @@
#define writew_relaxed(x, addr) writew(x, addr)
#define writel_relaxed(x, addr) writel(x, addr)
-extern void __iomem *__ioremap(unsigned long physaddr, unsigned long size,
- unsigned long cacheflag);
+void __iomem *ioremap(unsigned long physaddr, unsigned long size);
extern void __iounmap(void __iomem *addr);
-static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
-{
- return __ioremap(physaddr, size, 0);
-}
-
-static inline void __iomem *ioremap_nocache(unsigned long physaddr,
- unsigned long size)
-{
- return __ioremap(physaddr, size, 0);
-}
-
static inline void iounmap(void __iomem *addr)
{
__iounmap(addr);
}
-#define ioremap_nocache ioremap_nocache
-#define ioremap_wc ioremap_nocache
-#define ioremap_wt ioremap_nocache
+#define ioremap_nocache ioremap
+#define ioremap_wc ioremap
+#define ioremap_wt ioremap
/* Pages to physical address... */
#define page_to_phys(page) virt_to_phys(page_to_virt(page))
diff --git a/arch/nios2/mm/ioremap.c b/arch/nios2/mm/ioremap.c
index 3a28177a01eb..7a1a27f3daa3 100644
--- a/arch/nios2/mm/ioremap.c
+++ b/arch/nios2/mm/ioremap.c
@@ -112,8 +112,7 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
/*
* Map some physical address range into the kernel address space.
*/
-void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
- unsigned long cacheflag)
+void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
{
struct vm_struct *area;
unsigned long offset;
@@ -139,15 +138,6 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
return NULL;
}
- /*
- * Map uncached objects in the low part of address space to
- * CONFIG_NIOS2_IO_REGION_BASE
- */
- if (IS_MAPPABLE_UNCACHEABLE(phys_addr) &&
- IS_MAPPABLE_UNCACHEABLE(last_addr) &&
- !(cacheflag & _PAGE_CACHED))
- return (void __iomem *)(CONFIG_NIOS2_IO_REGION_BASE + phys_addr);
-
/* Mappings have to be page-aligned */
offset = phys_addr & ~PAGE_MASK;
phys_addr &= PAGE_MASK;
@@ -158,14 +148,13 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size,
- cacheflag)) {
+ if (remap_area_pages((unsigned long) addr, phys_addr, size, 0)) {
vunmap(addr);
return NULL;
}
return (void __iomem *) (offset + (char *)addr);
}
-EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(ioremap);
/*
* __iounmap unmaps nearly everything, so be careful
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 11/26] parisc: remove __ioremap
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
__ioremap is always called with the _PAGE_NO_CACHE, so fold the whole
thing and rename it to ioremap. This allows allows to remove the
special EISA quirk to force _PAGE_NO_CACHE.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/parisc/include/asm/io.h | 11 +----------
arch/parisc/mm/ioremap.c | 16 +++-------------
2 files changed, 4 insertions(+), 23 deletions(-)
diff --git a/arch/parisc/include/asm/io.h b/arch/parisc/include/asm/io.h
index 93d37010b375..46212b52c23e 100644
--- a/arch/parisc/include/asm/io.h
+++ b/arch/parisc/include/asm/io.h
@@ -127,16 +127,7 @@ static inline void gsc_writeq(unsigned long long val, unsigned long addr)
/*
* The standard PCI ioremap interfaces
*/
-
-extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
-
-/* Most machines react poorly to I/O-space being cacheable... Instead let's
- * define ioremap() in terms of ioremap_nocache().
- */
-static inline void __iomem * ioremap(unsigned long offset, unsigned long size)
-{
- return __ioremap(offset, size, _PAGE_NO_CACHE);
-}
+void __iomem *ioremap(unsigned long offset, unsigned long size);
#define ioremap_nocache(off, sz) ioremap((off), (sz))
#define ioremap_wc ioremap_nocache
#define ioremap_uc ioremap_nocache
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index 92a9b5f12f98..fe65e27f882b 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -25,23 +25,13 @@
* have to convert them into an offset in a page-aligned mapping, but the
* caller shouldn't need to know that small detail.
*/
-void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
{
void __iomem *addr;
struct vm_struct *area;
unsigned long offset, last_addr;
pgprot_t pgprot;
-#ifdef CONFIG_EISA
- unsigned long end = phys_addr + size - 1;
- /* Support EISA addresses */
- if ((phys_addr >= 0x00080000 && end < 0x000fffff) ||
- (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
- phys_addr |= F_EXTEND(0xfc000000);
- flags |= _PAGE_NO_CACHE;
- }
-#endif
-
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
if (!size || last_addr < phys_addr)
@@ -65,7 +55,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
}
pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
- _PAGE_ACCESSED | flags);
+ _PAGE_ACCESSED | _PAGE_NO_CACHE);
/*
* Mappings have to be page-aligned
@@ -90,7 +80,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
return (void __iomem *) (offset + (char __iomem *)addr);
}
-EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(ioremap);
void iounmap(const volatile void __iomem *addr)
{
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 12/26] x86: clean up ioremap
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
Use ioremap as the main implemented function, and defined
ioremap_nocache to it as a deprecated alias.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/x86/include/asm/io.h | 8 ++------
arch/x86/mm/ioremap.c | 8 ++++----
arch/x86/mm/pageattr.c | 4 ++--
3 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 6bed97ff6db2..6b5cc41319a7 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -180,8 +180,6 @@ static inline unsigned int isa_virt_to_bus(volatile void *address)
* The default ioremap() behavior is non-cached; if you need something
* else, you probably want one of the following.
*/
-extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
-#define ioremap_nocache ioremap_nocache
extern void __iomem *ioremap_uc(resource_size_t offset, unsigned long size);
#define ioremap_uc ioremap_uc
extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
@@ -205,11 +203,9 @@ extern void __iomem *ioremap_encrypted(resource_size_t phys_addr, unsigned long
* If the area you are trying to map is a PCI BAR you should have a
* look at pci_iomap().
*/
-static inline void __iomem *ioremap(resource_size_t offset, unsigned long size)
-{
- return ioremap_nocache(offset, size);
-}
+void __iomem *ioremap(resource_size_t offset, unsigned long size);
#define ioremap ioremap
+#define ioremap_nocache ioremap
extern void iounmap(volatile void __iomem *addr);
#define iounmap iounmap
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 63e99f15d7cf..c9e90211bddb 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -279,11 +279,11 @@ __ioremap_caller(resource_size_t phys_addr, unsigned long size,
}
/**
- * ioremap_nocache - map bus memory into CPU space
+ * ioremap - map bus memory into CPU space
* @phys_addr: bus address of the memory
* @size: size of the resource to map
*
- * ioremap_nocache performs a platform specific sequence of operations to
+ * ioremap performs a platform specific sequence of operations to
* make bus memory CPU accessible via the readb/readw/readl/writeb/
* writew/writel functions and the other mmio helpers. The returned
* address is not guaranteed to be usable directly as a virtual
@@ -299,7 +299,7 @@ __ioremap_caller(resource_size_t phys_addr, unsigned long size,
*
* Must be freed with iounmap.
*/
-void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
+void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
{
/*
* Ideally, this should be:
@@ -314,7 +314,7 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
return __ioremap_caller(phys_addr, size, pcm,
__builtin_return_address(0), false);
}
-EXPORT_SYMBOL(ioremap_nocache);
+EXPORT_SYMBOL(ioremap);
/**
* ioremap_uc - map bus memory into CPU space as strongly uncachable
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 6a9a77a403c9..5b7a9231b85b 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1774,7 +1774,7 @@ static inline int cpa_clear_pages_array(struct page **pages, int numpages,
int _set_memory_uc(unsigned long addr, int numpages)
{
/*
- * for now UC MINUS. see comments in ioremap_nocache()
+ * for now UC MINUS. see comments in ioremap()
* If you really need strong UC use ioremap_uc(), but note
* that you cannot override IO areas with set_memory_*() as
* these helpers cannot work with IO memory.
@@ -1789,7 +1789,7 @@ int set_memory_uc(unsigned long addr, int numpages)
int ret;
/*
- * for now UC MINUS. see comments in ioremap_nocache()
+ * for now UC MINUS. see comments in ioremap()
*/
ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
_PAGE_CACHE_MODE_UC_MINUS, NULL);
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 13/26] xtensa: clean up ioremap
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
Use ioremap as the main implemented function, and defined
ioremap_nocache to it as a deprecated alias.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/xtensa/include/asm/io.h | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
index da3e783f896b..ffadc99c8601 100644
--- a/arch/xtensa/include/asm/io.h
+++ b/arch/xtensa/include/asm/io.h
@@ -31,8 +31,7 @@ void xtensa_iounmap(volatile void __iomem *addr);
/*
* Return the virtual address for the specified bus memory.
*/
-static inline void __iomem *ioremap_nocache(unsigned long offset,
- unsigned long size)
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
{
if (offset >= XCHAL_KIO_PADDR
&& offset - XCHAL_KIO_PADDR < XCHAL_KIO_SIZE)
@@ -51,15 +50,10 @@ static inline void __iomem *ioremap_cache(unsigned long offset,
return xtensa_ioremap_cache(offset, size);
}
#define ioremap_cache ioremap_cache
-#define ioremap_nocache ioremap_nocache
-
-#define ioremap_wc ioremap_nocache
-#define ioremap_wt ioremap_nocache
-static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
-{
- return ioremap_nocache(offset, size);
-}
+#define ioremap_nocache ioremap
+#define ioremap_wc ioremap
+#define ioremap_wt ioremap
static inline void iounmap(volatile void __iomem *addr)
{
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 14/26] asm-generic: don't provide __ioremap
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
__ioremap is not a kernel API, but used for helpers with differing
semantics in arch code. We should not provide it in as-generic.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/asm-generic/io.h | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index b83e2802c969..d02806513670 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -963,15 +963,6 @@ static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
}
#endif
-#ifndef __ioremap
-#define __ioremap __ioremap
-static inline void __iomem *__ioremap(phys_addr_t offset, size_t size,
- unsigned long flags)
-{
- return ioremap(offset, size);
-}
-#endif
-
#ifndef iounmap
#define iounmap iounmap
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 15/26] asm-generic: ioremap_uc should behave the same with and without MMU
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
Whatever reason there is for the existence of ioremap_uc, and the fact
that it returns NULL by default on architectures with an MMU applies
equally to nommu architectures, so don't provide different defaults.
In practice the difference is meaningless as the only portable driver
that uses ioremap_uc is atyfb which probably doesn't show up on nommu
devices.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/asm-generic/io.h | 36 ++++++++++++++++--------------------
1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index d02806513670..a98ed6325727 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -935,18 +935,7 @@ static inline void *phys_to_virt(unsigned long address)
* defined your own ioremap_*() variant you must then declare your own
* ioremap_*() variant as defined to itself to avoid the default NULL return.
*/
-
-#ifdef CONFIG_MMU
-
-#ifndef ioremap_uc
-#define ioremap_uc ioremap_uc
-static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
-{
- return NULL;
-}
-#endif
-
-#else /* !CONFIG_MMU */
+#ifndef CONFIG_MMU
/*
* Change "struct page" to physical address.
@@ -980,14 +969,6 @@ static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
}
#endif
-#ifndef ioremap_uc
-#define ioremap_uc ioremap_uc
-static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
-{
- return ioremap_nocache(offset, size);
-}
-#endif
-
#ifndef ioremap_wc
#define ioremap_wc ioremap_wc
static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
@@ -1004,6 +985,21 @@ static inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size)
}
#endif
+/*
+ * ioremap_uc is special in that we do require an explicit architecture
+ * implementation. In general you do now want to use this function in a
+ * driver and use plain ioremap, which is uncached by default. Similarly
+ * architectures should not implement it unless they have a very good
+ * reason.
+ */
+#ifndef ioremap_uc
+#define ioremap_uc ioremap_uc
+static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
+{
+ return NULL;
+}
+#endif
+
#ifdef CONFIG_HAS_IOPORT_MAP
#ifndef CONFIG_GENERIC_IOMAP
#ifndef ioport_map
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 16/26] asm-generic: don't provide ioremap for CONFIG_MMU
From: Christoph Hellwig @ 2019-08-17 7:32 UTC (permalink / raw)
To: Arnd Bergmann, Guo Ren, Michal Simek, Greentime Hu, Vincent Chen,
Guan Xuetao, x86
Cc: linux-arch, linux-s390, linux-ia64, linux-parisc, linux-sh,
linux-hexagon, linux-xtensa, linux-mips, linux-kernel, linux-m68k,
openrisc, linux-mtd, linux-alpha, sparclinux, nios2-dev,
linux-riscv, linux-snps-arc, linux-arm-kernel
In-Reply-To: <20190817073253.27819-1-hch@lst.de>
All MMU-enabled ports have a non-trivial ioremap and should thus provide
the prototype for their implementation instead of providing a generic
one unless a different symbol is not defined. Note that this only
affects sparc32 nds32 as all others do provide their own version.
Also update the kerneldoc comments in asm-generic/io.h to explain the
situation around the default ioremap* implementations correctly.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/nds32/include/asm/io.h | 2 ++
arch/sparc/include/asm/io_32.h | 1 +
include/asm-generic/io.h | 29 ++++++++---------------------
3 files changed, 11 insertions(+), 21 deletions(-)
diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h
index 16f262322b8f..fb0e8a24c7af 100644
--- a/arch/nds32/include/asm/io.h
+++ b/arch/nds32/include/asm/io.h
@@ -6,6 +6,7 @@
#include <linux/types.h>
+void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
extern void iounmap(volatile void __iomem *addr);
#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
@@ -80,4 +81,5 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
#define writew(v,c) ({ __iowmb(); writew_relaxed((v),(c)); })
#define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c)); })
#include <asm-generic/io.h>
+
#endif /* __ASM_NDS32_IO_H */
diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h
index df2dc1784673..9a52d9506f80 100644
--- a/arch/sparc/include/asm/io_32.h
+++ b/arch/sparc/include/asm/io_32.h
@@ -127,6 +127,7 @@ static inline void sbus_memcpy_toio(volatile void __iomem *dst,
* Bus number may be embedded in the higher bits of the physical address.
* This is why we have no bus number argument to ioremap().
*/
+void __iomem *ioremap(phys_addr_t offset, size_t size);
void iounmap(volatile void __iomem *addr);
/* Create a virtual mapping cookie for an IO port range */
void __iomem *ioport_map(unsigned long port, unsigned int nr);
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index a98ed6325727..6a5edc23afe2 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -922,28 +922,16 @@ static inline void *phys_to_virt(unsigned long address)
/**
* DOC: ioremap() and ioremap_*() variants
*
- * If you have an IOMMU your architecture is expected to have both ioremap()
- * and iounmap() implemented otherwise the asm-generic helpers will provide a
- * direct mapping.
+ * Architectures with an MMU are expected to provide ioremap() and iounmap()
+ * themselves. For NOMMU architectures we provide a default nop-op
+ * implementation that expect that the physical address used for MMIO are
+ * already marked as uncached, and can be used as kernel virtual addresses.
*
- * There are ioremap_*() call variants, if you have no IOMMU we naturally will
- * default to direct mapping for all of them, you can override these defaults.
- * If you have an IOMMU you are highly encouraged to provide your own
- * ioremap variant implementation as there currently is no safe architecture
- * agnostic default. To avoid possible improper behaviour default asm-generic
- * ioremap_*() variants all return NULL when an IOMMU is available. If you've
- * defined your own ioremap_*() variant you must then declare your own
- * ioremap_*() variant as defined to itself to avoid the default NULL return.
+ * ioremap_wc() and ioremap_wt() can provide more relaxed caching attributes
+ * for specific drivers if the architecture choses to implement them. If they
+ * are not implemented we fall back to plain ioremap.
*/
#ifndef CONFIG_MMU
-
-/*
- * Change "struct page" to physical address.
- *
- * This implementation is for the no-MMU case only... if you have an MMU
- * you'll need to provide your own definitions.
- */
-
#ifndef ioremap
#define ioremap ioremap
static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
@@ -954,14 +942,13 @@ static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
#ifndef iounmap
#define iounmap iounmap
-
static inline void iounmap(void __iomem *addr)
{
}
#endif
#endif /* CONFIG_MMU */
+
#ifndef ioremap_nocache
-void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
#define ioremap_nocache ioremap_nocache
static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
{
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox